MCPcopy Index your code
hub / github.com/coder/coder / AuthorizeDevice

Method AuthorizeDevice

coderd/externalauth/externalauth.go:671–735  ·  view source on GitHub ↗

AuthorizeDevice begins the device authorization flow. See: https://tools.ietf.org/html/rfc8628#section-3.1

(ctx context.Context)

Source from the content-addressed store, hash-verified

669// AuthorizeDevice begins the device authorization flow.
670// See: https://tools.ietf.org/html/rfc8628#section-3.1
671func (c *DeviceAuth) AuthorizeDevice(ctx context.Context) (*codersdk.ExternalAuthDevice, error) {
672 if c.CodeURL == "" {
673 return nil, xerrors.New("oauth2: device code URL not set")
674 }
675 codeURL, err := c.formatDeviceCodeURL()
676 if err != nil {
677 return nil, err
678 }
679 req, err := http.NewRequestWithContext(ctx, http.MethodPost, codeURL, nil)
680 if err != nil {
681 return nil, err
682 }
683 req.Header.Set("Accept", "application/json")
684
685 do := http.DefaultClient.Do
686 if c.Config != nil {
687 // The cfg can be nil in unit tests.
688 do = func(req *http.Request) (*http.Response, error) {
689 return c.Config.Do(ctx, promoauth.SourceAuthorizeDevice, req)
690 }
691 }
692
693 resp, err := do(req)
694 if err != nil {
695 return nil, err
696 }
697 defer resp.Body.Close()
698 var r struct {
699 codersdk.ExternalAuthDevice
700 ErrorDescription string `json:"error_description"`
701 }
702 err = json.NewDecoder(resp.Body).Decode(&r)
703 if err != nil {
704 mediaType, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
705 if err != nil {
706 mediaType = "unknown"
707 }
708
709 // If the json fails to decode, do a best effort to return a better error.
710 switch {
711 case resp.StatusCode == http.StatusTooManyRequests:
712 retryIn := "please try again later"
713 resetIn := resp.Header.Get("x-ratelimit-reset")
714 if resetIn != "" {
715 // Best effort to tell the user exactly how long they need
716 // to wait for.
717 unix, err := strconv.ParseInt(resetIn, 10, 64)
718 if err == nil {
719 waitFor := time.Unix(unix, 0).Sub(time.Now().Truncate(time.Second))
720 retryIn = fmt.Sprintf(" retry after %s", waitFor.Truncate(time.Second))
721 }
722 }
723 // 429 returns a plaintext payload with a message.
724 return nil, xerrors.New(fmt.Sprintf("rate limit hit, unable to authorize device. %s", retryIn))
725 case mediaType == "application/x-www-form-urlencoded":
726 return nil, xerrors.Errorf("status_code=%d, payload response is form-url encoded, expected a json payload", resp.StatusCode)
727 default:
728 return nil, xerrors.Errorf("status_code=%d, mediaType=%s: %w", resp.StatusCode, mediaType, err)

Callers 3

configureGithubOAuth2Function · 0.95

Calls 7

formatDeviceCodeURLMethod · 0.95
NewMethod · 0.65
SetMethod · 0.65
DoMethod · 0.65
CloseMethod · 0.65
GetMethod · 0.65
ErrorfMethod · 0.45

Tested by

no test coverage detected