// InitiateDeviceAuth initiates a device auth flow. It returns a DeviceCode // that can be used with CheckForUserCompletion or WaitForUserCompletion. func InitiateDeviceAuth(client *autorest.Client, oauthConfig OAuthConfig, clientID, resource string) (*DeviceCode, error) { req, _ := autorest.Prepare( &http.Request{}, autorest.AsPost(), autorest.AsFormURLEncoded(), autorest.WithBaseURL(oauthConfig.DeviceCodeEndpoint.String()), autorest.WithFormData(url.Values{ "client_id": []string{clientID}, "resource": []string{resource}, }), ) resp, err := client.Send(req) if err != nil { return nil, fmt.Errorf("%s %s: %s", logPrefix, errCodeSendingFails, err) } var code DeviceCode err = autorest.Respond( resp, autorest.WithErrorUnlessStatusCode(http.StatusOK), autorest.ByUnmarshallingJSON(&code), autorest.ByClosing()) if err != nil { return nil, fmt.Errorf("%s %s: %s", logPrefix, errCodeHandlingFails, err) } code.ClientID = clientID code.Resource = resource code.OAuthConfig = oauthConfig return &code, nil }
func (spt *ServicePrincipalToken) refreshInternal(resource string) error { v := url.Values{} v.Set("client_id", spt.clientID) v.Set("resource", resource) if spt.RefreshToken != "" { v.Set("grant_type", OAuthGrantTypeRefreshToken) v.Set("refresh_token", spt.RefreshToken) } else { v.Set("grant_type", OAuthGrantTypeClientCredentials) err := spt.secret.SetAuthenticationValues(spt, &v) if err != nil { return err } } req, _ := autorest.Prepare(&http.Request{}, autorest.AsPost(), autorest.AsFormURLEncoded(), autorest.WithBaseURL(spt.oauthConfig.TokenEndpoint.String()), autorest.WithFormData(v)) resp, err := autorest.SendWithSender(spt.sender, req) if err != nil { return autorest.NewErrorWithError(err, "azure.ServicePrincipalToken", "Refresh", resp, "Failure sending request for Service Principal %s", spt.clientID) } var newToken Token err = autorest.Respond(resp, autorest.WithErrorUnlessOK(), autorest.ByUnmarshallingJSON(&newToken), autorest.ByClosing()) if err != nil { return autorest.NewErrorWithError(err, "azure.ServicePrincipalToken", "Refresh", resp, "Failure handling response to Service Principal %s request", spt.clientID) } spt.Token = newToken err = spt.InvokeRefreshCallbacks(newToken) if err != nil { // its already wrapped inside InvokeRefreshCallbacks return err } return nil }
// Refresh obtains a fresh token for the Service Principal. func (spt *ServicePrincipalToken) Refresh() error { p := map[string]interface{}{ "tenantID": spt.tenantID, "requestType": "token", } v := url.Values{} v.Set("client_id", spt.clientID) v.Set("grant_type", "client_credentials") v.Set("resource", spt.resource) err := spt.secret.SetAuthenticationValues(spt, &v) if err != nil { return err } req, err := autorest.Prepare(&http.Request{}, autorest.AsPost(), autorest.AsFormURLEncoded(), autorest.WithBaseURL(oauthURL), autorest.WithPathParameters(p), autorest.WithFormData(v)) if err != nil { return err } resp, err := autorest.SendWithSender(spt.sender, req) if err != nil { return autorest.NewErrorWithError(err, "azure.ServicePrincipalToken", "Refresh", "Failure sending request for Service Principal %s", spt.clientID) } var newToken Token err = autorest.Respond(resp, autorest.WithErrorUnlessOK(), autorest.ByUnmarshallingJSON(&newToken), autorest.ByClosing()) if err != nil { return autorest.NewErrorWithError(err, "azure.ServicePrincipalToken", "Refresh", "Failure handling response to Service Principal %s request", spt.clientID) } spt.Token = newToken return nil }
// CheckForUserCompletion takes a DeviceCode and checks with the Azure AD OAuth endpoint // to see if the device flow has: been completed, timed out, or otherwise failed func CheckForUserCompletion(client *autorest.Client, code *DeviceCode) (*Token, error) { req, _ := autorest.Prepare( &http.Request{}, autorest.AsPost(), autorest.AsFormURLEncoded(), autorest.WithBaseURL(code.OAuthConfig.TokenEndpoint.String()), autorest.WithFormData(url.Values{ "client_id": []string{code.ClientID}, "code": []string{*code.DeviceCode}, "grant_type": []string{OAuthGrantTypeDeviceCode}, "resource": []string{code.Resource}, }), ) resp, err := client.Send(req) if err != nil { return nil, fmt.Errorf("%s %s: %s", logPrefix, errTokenSendingFails, err) } var token deviceToken err = autorest.Respond( resp, autorest.WithErrorUnlessStatusCode(http.StatusOK, http.StatusBadRequest), autorest.ByUnmarshallingJSON(&token), autorest.ByClosing()) if err != nil { return nil, fmt.Errorf("%s %s: %s", logPrefix, errTokenHandlingFails, err) } if token.Error == nil { return &token.Token, nil } switch *token.Error { case "authorization_pending": return nil, ErrDeviceAuthorizationPending case "slow_down": return nil, ErrDeviceSlowDown case "access_denied": return nil, ErrDeviceAccessDenied case "code_expired": return nil, ErrDeviceCodeExpired default: return nil, ErrDeviceGeneric } }