| 586 | } |
| 587 | |
| 588 | func newOauth(provider, clientID, clientSecret, authzEp, deviceAuthzEp, tokenEp, scope, prompt string, authParams url.Values, opts *options) (*oauth, error) { |
| 589 | state, err := randutil.Alphanumeric(32) |
| 590 | if err != nil { |
| 591 | return nil, err |
| 592 | } |
| 593 | |
| 594 | challenge, err := randutil.Alphanumeric(64) |
| 595 | if err != nil { |
| 596 | return nil, err |
| 597 | } |
| 598 | |
| 599 | nonce, err := randutil.Hex(64) // 256 bits |
| 600 | if err != nil { |
| 601 | return nil, err |
| 602 | } |
| 603 | |
| 604 | // Check known providers |
| 605 | if p, ok := knownProviders[provider]; ok { |
| 606 | return &oauth{ |
| 607 | provider: provider, |
| 608 | clientID: clientID, |
| 609 | clientSecret: clientSecret, |
| 610 | scope: scope, |
| 611 | prompt: prompt, |
| 612 | authzEndpoint: p.authorization, |
| 613 | deviceAuthzEndpoint: p.deviceAuthorization, |
| 614 | tokenEndpoint: p.token, |
| 615 | userInfoEndpoint: p.userInfo, |
| 616 | loginHint: opts.Email, |
| 617 | state: state, |
| 618 | codeChallenge: challenge, |
| 619 | nonce: nonce, |
| 620 | implicit: opts.Implicit, |
| 621 | CallbackListener: opts.CallbackListener, |
| 622 | CallbackListenerURL: opts.CallbackListenerURL, |
| 623 | CallbackPath: opts.CallbackPath, |
| 624 | terminalRedirect: opts.TerminalRedirect, |
| 625 | browser: opts.Browser, |
| 626 | authParams: authParams, |
| 627 | errCh: make(chan error), |
| 628 | tokCh: make(chan *token), |
| 629 | }, nil |
| 630 | } |
| 631 | |
| 632 | userinfoEp := "" |
| 633 | isDeviceFlow := opts.Console && opts.ConsoleFlow == deviceConsoleFlow |
| 634 | |
| 635 | if (isDeviceFlow && deviceAuthzEp == "" && tokenEp == "") || (!isDeviceFlow && authzEp == "" && tokenEp == "") { |
| 636 | d, err := disco(provider) |
| 637 | if err != nil { |
| 638 | return nil, err |
| 639 | } |
| 640 | |
| 641 | if v, ok := d["device_authorization_endpoint"].(string); !ok && isDeviceFlow { |
| 642 | return nil, errors.New("missing or invalid 'device_authorization_endpoint' in provider metadata") |
| 643 | } else if ok { |
| 644 | deviceAuthzEp = v |
| 645 | } |