GetDeviceCode initiates the device-code auth flow with the tenant. The state returned contains the device code that the user must use to authenticate, as well as the URL to visit, etc.
(ctx context.Context, audience string)
| 53 | // The state returned contains the device code that the user must use to |
| 54 | // authenticate, as well as the URL to visit, etc. |
| 55 | func (a API) GetDeviceCode(ctx context.Context, audience string) (State, error) { |
| 56 | data := url.Values{ |
| 57 | "client_id": {a.ClientID}, |
| 58 | "audience": {audience}, |
| 59 | "scope": {strings.Join(a.Scopes, " ")}, |
| 60 | } |
| 61 | |
| 62 | deviceCodeURL := a.TenantURL + "/oauth/device/code" |
| 63 | resp, err := postForm(ctx, deviceCodeURL, strings.NewReader(data.Encode())) |
| 64 | if err != nil { |
| 65 | return State{}, err |
| 66 | } |
| 67 | defer func() { |
| 68 | _ = resp.Body.Close() |
| 69 | }() |
| 70 | |
| 71 | if resp.StatusCode != http.StatusOK { |
| 72 | return State{}, tryDecodeOAuthError(resp) |
| 73 | } |
| 74 | |
| 75 | var state State |
| 76 | err = json.NewDecoder(resp.Body).Decode(&state) |
| 77 | if err != nil { |
| 78 | return state, fmt.Errorf("failed to get device code: %w", err) |
| 79 | } |
| 80 | |
| 81 | return state, nil |
| 82 | } |
| 83 | |
| 84 | func tryDecodeOAuthError(resp *http.Response) error { |
| 85 | var body map[string]any |