func (s *Service) clientCredentialsGrant(w http.ResponseWriter, r *http.Request, client *Client) { // Get the scope string scope, err := s.GetScope(r.Form.Get("scope")) if err != nil { response.Error(w, err.Error(), http.StatusBadRequest) return } // Create a new access token accessToken, err := s.GrantAccessToken( client, new(User), // empty user s.cnf.Oauth.AccessTokenLifetime, // expires in scope, ) if err != nil { response.Error(w, err.Error(), http.StatusInternalServerError) return } // Write the JSON access token to the response accessTokenRespone := &AccessTokenResponse{ AccessToken: accessToken.Token, ExpiresIn: s.cnf.Oauth.AccessTokenLifetime, TokenType: TokenType, Scope: accessToken.Scope, } response.WriteJSON(w, accessTokenRespone, 200) }
func (s *Service) refreshTokenGrant(w http.ResponseWriter, r *http.Request, client *Client) { // Fetch the refresh token theRefreshToken, err := s.GetValidRefreshToken( r.Form.Get("refresh_token"), // refresh token client, // client ) if err != nil { response.Error(w, err.Error(), http.StatusBadRequest) return } // Get the scope string scope, err := s.GetScope(r.Form.Get("scope")) if err != nil { response.Error(w, err.Error(), http.StatusBadRequest) return } // Requested scope CANNOT include any scope not originally granted if !util.SpaceDelimitedStringNotGreater(scope, theRefreshToken.Scope) { response.Error(w, errRequestedScopeCannotBeGreater.Error(), http.StatusBadRequest) return } // Create a new access token accessToken, err := s.GrantAccessToken( theRefreshToken.Client, // client theRefreshToken.User, // user scope, // scope ) if err != nil { response.Error(w, err.Error(), http.StatusInternalServerError) return } // Create or retrieve a refresh token refreshToken, err := s.GetOrCreateRefreshToken( theRefreshToken.Client, // client theRefreshToken.User, // user scope, // scope ) if err != nil { response.Error(w, err.Error(), http.StatusInternalServerError) return } // Write the JSON access token to the response accessTokenRespone := &AccessTokenResponse{ ID: accessToken.ID, AccessToken: accessToken.Token, ExpiresIn: s.cnf.Oauth.AccessTokenLifetime, TokenType: "Bearer", Scope: accessToken.Scope, RefreshToken: refreshToken.Token, } response.WriteJSON(w, accessTokenRespone, 200) }
func (s *Service) authorizationCodeGrant(w http.ResponseWriter, r *http.Request, client *Client) { // Fetch the authorization code authorizationCode, err := s.getValidAuthorizationCode( r.Form.Get("code"), // authorization code client, // client ) if err != nil { response.Error(w, err.Error(), http.StatusBadRequest) return } // Redirect URI must match if it was used to obtain the authorization code if util.StringOrNull(r.Form.Get("redirect_uri")) != authorizationCode.RedirectURI { response.Error(w, errInvalidRedirectURI.Error(), http.StatusBadRequest) return } // Create a new access token accessToken, err := s.GrantAccessToken( authorizationCode.Client, // client authorizationCode.User, // user authorizationCode.Scope, // scope ) if err != nil { response.Error(w, err.Error(), http.StatusInternalServerError) return } // Create or retrieve a refresh token refreshToken, err := s.GetOrCreateRefreshToken( authorizationCode.Client, // client authorizationCode.User, // user authorizationCode.Scope, // scope ) if err != nil { response.Error(w, err.Error(), http.StatusInternalServerError) return } // Delete the authorization code s.db.Unscoped().Delete(&authorizationCode) // Write the JSON access token to the response accessTokenRespone := &AccessTokenResponse{ ID: accessToken.ID, AccessToken: accessToken.Token, ExpiresIn: s.cnf.Oauth.AccessTokenLifetime, TokenType: "Bearer", Scope: accessToken.Scope, RefreshToken: refreshToken.Token, } response.WriteJSON(w, accessTokenRespone, 200) }
func (s *Service) refreshTokenGrant(w http.ResponseWriter, r *http.Request, client *Client) { // Fetch the refresh token theRefreshToken, err := s.GetValidRefreshToken( r.Form.Get("refresh_token"), // refresh token client, // client ) if err != nil { response.Error(w, err.Error(), http.StatusBadRequest) return } // Default to the scope originally granted by the resource owner scope := theRefreshToken.Scope // If the scope is specified in the request, get the scope string if r.Form.Get("scope") != "" { scope, err = s.GetScope(r.Form.Get("scope")) if err != nil { response.Error(w, err.Error(), http.StatusBadRequest) return } } // Requested scope CANNOT include any scope not originally granted if !util.SpaceDelimitedStringNotGreater(scope, theRefreshToken.Scope) { response.Error(w, ErrRequestedScopeCannotBeGreater.Error(), http.StatusBadRequest) return } // Log in the user accessToken, refreshToken, err := s.Login( theRefreshToken.Client, theRefreshToken.User, scope, ) if err != nil { response.Error(w, err.Error(), http.StatusInternalServerError) return } // Write the JSON access token to the response accessTokenRespone := &AccessTokenResponse{ AccessToken: accessToken.Token, ExpiresIn: s.cnf.Oauth.AccessTokenLifetime, TokenType: TokenType, Scope: accessToken.Scope, RefreshToken: refreshToken.Token, } if accessToken.User != nil { accessTokenRespone.UserID = accessToken.User.ID } response.WriteJSON(w, accessTokenRespone, 200) }
func (s *Service) passwordGrant(w http.ResponseWriter, r *http.Request, client *Client) { // Get user credentials from form data username := r.Form.Get("username") // usually an email password := r.Form.Get("password") // Authenticate the user user, err := s.AuthUser(username, password) if err != nil { // For security reasons, return a general error message response.UnauthorizedError(w, "User authentication required") return } // Get the scope string scope, err := s.GetScope(r.Form.Get("scope")) if err != nil { response.Error(w, err.Error(), http.StatusBadRequest) return } // Create a new access token accessToken, err := s.GrantAccessToken( client, // client user, // user scope, // scope ) if err != nil { response.Error(w, err.Error(), http.StatusInternalServerError) return } // Create or retrieve a refresh token refreshToken, err := s.GetOrCreateRefreshToken( client, // client user, // user scope, // scope ) if err != nil { response.Error(w, err.Error(), http.StatusInternalServerError) return } // Write the JSON access token to the response accessTokenRespone := &AccessTokenResponse{ ID: accessToken.ID, AccessToken: accessToken.Token, ExpiresIn: s.cnf.Oauth.AccessTokenLifetime, TokenType: "Bearer", Scope: accessToken.Scope, RefreshToken: refreshToken.Token, } response.WriteJSON(w, accessTokenRespone, 200) }
func (s *Service) introspectToken(w http.ResponseWriter, r *http.Request, client *Client) { // Parse the form so r.Form becomes available if err := r.ParseForm(); err != nil { response.Error(w, err.Error(), http.StatusInternalServerError) return } token := r.Form.Get("token") if token == "" { response.Error(w, ErrTokenMissing.Error(), http.StatusBadRequest) return } tokenTypeHint := r.Form.Get("token_type_hint") if tokenTypeHint == "" { tokenTypeHint = accessTokenHint } var ir *IntrospectResponse switch tokenTypeHint { case accessTokenHint: var ok bool ir, ok = s.introspectAccessToken(w, token) if !ok { ir, _ = s.introspectRefreshToken(w, token, client) } case refreshTokenHint: var ok bool ir, ok = s.introspectRefreshToken(w, token, client) if !ok { ir, _ = s.introspectAccessToken(w, token) } default: response.Error(w, ErrTokenHintInvalid.Error(), http.StatusBadRequest) return } if ir == nil { ir = &IntrospectResponse{} } response.WriteJSON(w, ir, 200) }
// Handles all OAuth 2.0 grant types (POST /v1/oauth/tokens) func (s *Service) tokensHandler(w http.ResponseWriter, r *http.Request) { // Parse the form so r.Form becomes available if err := r.ParseForm(); err != nil { response.Error(w, err.Error(), http.StatusInternalServerError) return } // Map of grant types against handler functions grantTypes := map[string]func(w http.ResponseWriter, r *http.Request, client *Client){ "authorization_code": s.authorizationCodeGrant, "password": s.passwordGrant, "client_credentials": s.clientCredentialsGrant, "refresh_token": s.refreshTokenGrant, } // Check the grant type grantHandler, ok := grantTypes[r.Form.Get("grant_type")] if !ok { response.Error(w, errInvalidGrantType.Error(), http.StatusBadRequest) return } // Get client credentials from basic auth clientID, secret, ok := r.BasicAuth() if !ok { response.UnauthorizedError(w, errClientAuthenticationRequired.Error()) return } // Authenticate the client client, err := s.AuthClient(clientID, secret) if err != nil { // For security reasons, return a general error message response.UnauthorizedError(w, errClientAuthenticationRequired.Error()) return } // Execute the correct function based on the grant type grantHandler(w, r, client) }