GetDeviceCode kicks-off the device authentication flow by requesting a device code from Auth0. The returned state contains the URI for the next step of the flow.
(ctx context.Context, httpClient *http.Client, additionalScopes []string, domain string)
| 154 | // a device code from Auth0. The returned state contains the |
| 155 | // URI for the next step of the flow. |
| 156 | func GetDeviceCode(ctx context.Context, httpClient *http.Client, additionalScopes []string, domain string) (State, error) { |
| 157 | a := credentials |
| 158 | |
| 159 | data := url.Values{ |
| 160 | "client_id": []string{a.ClientID}, |
| 161 | "scope": []string{strings.Join(append(RequiredScopes, additionalScopes...), " ")}, |
| 162 | "audience": []string{domain}, |
| 163 | } |
| 164 | |
| 165 | request, err := http.NewRequestWithContext( |
| 166 | ctx, |
| 167 | http.MethodPost, |
| 168 | a.DeviceCodeEndpoint, |
| 169 | strings.NewReader(data.Encode()), |
| 170 | ) |
| 171 | if err != nil { |
| 172 | return State{}, fmt.Errorf("failed to create the request: %w", err) |
| 173 | } |
| 174 | |
| 175 | request.Header.Set("Content-Type", "application/x-www-form-urlencoded") |
| 176 | |
| 177 | response, err := httpClient.Do(request) |
| 178 | if err != nil { |
| 179 | return State{}, fmt.Errorf("failed to send the request: %w", err) |
| 180 | } |
| 181 | defer func() { |
| 182 | _ = response.Body.Close() |
| 183 | }() |
| 184 | |
| 185 | if response.StatusCode != http.StatusOK { |
| 186 | bodyBytes, err := io.ReadAll(response.Body) |
| 187 | if err != nil { |
| 188 | return State{}, fmt.Errorf( |
| 189 | "received a %d response and failed to read the response", |
| 190 | response.StatusCode, |
| 191 | ) |
| 192 | } |
| 193 | |
| 194 | return State{}, fmt.Errorf("received a %d response: %s", response.StatusCode, bodyBytes) |
| 195 | } |
| 196 | |
| 197 | var state State |
| 198 | if err = json.NewDecoder(response.Body).Decode(&state); err != nil { |
| 199 | return State{}, fmt.Errorf("failed to decode the response: %w", err) |
| 200 | } |
| 201 | |
| 202 | return state, nil |
| 203 | } |
| 204 | |
| 205 | func parseTenant(accessToken string) (tenant, domain string, err error) { |
| 206 | parts := strings.Split(accessToken, ".") |