WaitUntilUserLogsIn waits until the user is logged in on the browser.
(ctx context.Context, httpClient *http.Client, state State)
| 62 | |
| 63 | // WaitUntilUserLogsIn waits until the user is logged in on the browser. |
| 64 | func WaitUntilUserLogsIn(ctx context.Context, httpClient *http.Client, state State) (Result, error) { |
| 65 | t := time.NewTicker(state.IntervalDuration()) |
| 66 | for { |
| 67 | select { |
| 68 | case <-ctx.Done(): |
| 69 | return Result{}, ctx.Err() |
| 70 | case <-t.C: |
| 71 | data := url.Values{ |
| 72 | "client_id": []string{credentials.ClientID}, |
| 73 | "grant_type": []string{"urn:ietf:params:oauth:grant-type:device_code"}, |
| 74 | "device_code": []string{state.DeviceCode}, |
| 75 | } |
| 76 | r, err := httpClient.PostForm(credentials.OauthTokenEndpoint, data) |
| 77 | if err != nil { |
| 78 | return Result{}, fmt.Errorf("cannot get device code: %w", err) |
| 79 | } |
| 80 | defer func() { |
| 81 | _ = r.Body.Close() |
| 82 | }() |
| 83 | |
| 84 | var res struct { |
| 85 | AccessToken string `json:"access_token"` |
| 86 | IDToken string `json:"id_token"` |
| 87 | Scope string `json:"scope"` |
| 88 | ExpiresIn int64 `json:"expires_in"` |
| 89 | TokenType string `json:"token_type"` |
| 90 | Error *string `json:"error,omitempty"` |
| 91 | ErrorDescription string `json:"error_description,omitempty"` |
| 92 | } |
| 93 | |
| 94 | err = json.NewDecoder(r.Body).Decode(&res) |
| 95 | if err != nil { |
| 96 | return Result{}, fmt.Errorf("cannot decode response: %w", err) |
| 97 | } |
| 98 | |
| 99 | if res.Error != nil { |
| 100 | if *res.Error == "authorization_pending" { |
| 101 | continue |
| 102 | } |
| 103 | return Result{}, errors.New(res.ErrorDescription) |
| 104 | } |
| 105 | |
| 106 | ten, domain, err := parseTenant(res.AccessToken) |
| 107 | if err != nil { |
| 108 | return Result{}, fmt.Errorf("cannot parse tenant from the given access token: %w", err) |
| 109 | } |
| 110 | |
| 111 | return Result{ |
| 112 | AccessToken: res.AccessToken, |
| 113 | ExpiresAt: time.Now().Add( |
| 114 | time.Duration(res.ExpiresIn) * time.Second, |
| 115 | ), |
| 116 | Tenant: ten, |
| 117 | Domain: domain, |
| 118 | }, nil |
| 119 | } |
| 120 | } |
| 121 | } |