func (o *OAuthHandlers) generateOAuthOutputFromOsinResponse(osinResponse *osin.Response) ([]byte, bool) { // TODO: Might need to clear this out if osinResponse.Output["state"] == "" { log.Debug("Removing state") delete(osinResponse.Output, "state") } redirect, rediErr := osinResponse.GetRedirectUrl() if rediErr == nil { // Hack to inject redirect into response osinResponse.Output["redirect_to"] = redirect } if respData, marshalErr := json.Marshal(&osinResponse.Output); marshalErr != nil { return []byte{}, false } else { return respData, true } }
// encodeIDToken serializes and signs an ID Token then adds a field to the token response. func encodeIDToken(resp *osin.Response, idToken *IDToken, singer jose.Signer) { resp.InternalError = func() error { payload, err := json.Marshal(idToken) if err != nil { return fmt.Errorf("failed to marshal token: %v", err) } jws, err := jwtSigner.Sign(payload) if err != nil { return fmt.Errorf("failed to sign token: %v", err) } raw, err := jws.CompactSerialize() if err != nil { return fmt.Errorf("failed to serialize token: %v", err) } resp.Output["id_token"] = raw return nil }() // Record errors as internal server errors. if resp.InternalError != nil { resp.IsError = true resp.ErrorId = osin.E_SERVER_ERROR } }
// HandleAuthorize implements osinserver.AuthorizeHandler to ensure the requested scopes have been authorized. // The AuthorizeRequest.Authorized field must already be set to true for the grant check to occur. // If the requested scopes are authorized, the AuthorizeRequest is unchanged. // If the requested scopes are not authorized, or an error occurs, AuthorizeRequest.Authorized is set to false. // If the response is written, true is returned. // If the response is not written, false is returned. func (h *GrantCheck) HandleAuthorize(ar *osin.AuthorizeRequest, resp *osin.Response, w http.ResponseWriter) (bool, error) { // Requests must already be authorized before we will check grants if !ar.Authorized { return false, nil } // Reset request to unauthorized until we verify the grant ar.Authorized = false user, ok := ar.UserData.(user.Info) if !ok || user == nil { utilruntime.HandleError(fmt.Errorf("the provided user data is not a user.Info object: %#v", user)) resp.SetError("server_error", "") return false, nil } client, ok := ar.Client.GetUserData().(*oauthapi.OAuthClient) if !ok || client == nil { utilruntime.HandleError(fmt.Errorf("the provided client is not an *api.OAuthClient object: %#v", client)) resp.SetError("server_error", "") return false, nil } // Normalize the scope request, and ensure all tokens contain a scope scopes := scope.Split(ar.Scope) if len(scopes) == 0 { scopes = append(scopes, scopeauthorizer.UserFull) } ar.Scope = scope.Join(scopes) // Validate the requested scopes if scopeErrors := validation.ValidateScopes(scopes, nil); len(scopeErrors) > 0 { resp.SetError("invalid_scope", scopeErrors.ToAggregate().Error()) return false, nil } invalidScopes := sets.NewString() for _, scope := range scopes { if err := scopeauthorizer.ValidateScopeRestrictions(client, scope); err != nil { invalidScopes.Insert(scope) } } if len(invalidScopes) > 0 { resp.SetError("access_denied", fmt.Sprintf("scope denied: %s", strings.Join(invalidScopes.List(), " "))) return false, nil } grant := &api.Grant{ Client: ar.Client, Scope: ar.Scope, Expiration: int64(ar.Expiration), RedirectURI: ar.RedirectUri, } // Check if the user has already authorized this grant authorized, err := h.check.HasAuthorizedClient(user, grant) if err != nil { utilruntime.HandleError(err) resp.SetError("server_error", "") return false, nil } if authorized { ar.Authorized = true return false, nil } // React to an unauthorized grant authorized, handled, err := h.handler.GrantNeeded(user, grant, w, ar.HttpRequest) if authorized { ar.Authorized = true } return handled, err }