github.com/Richardknop/go-oauth2-server@v1.0.1/web/authorize.go (about) 1 package web 2 3 import ( 4 "errors" 5 "fmt" 6 "net/http" 7 "net/url" 8 "strconv" 9 10 "github.com/RichardKnop/go-oauth2-server/models" 11 "github.com/RichardKnop/go-oauth2-server/session" 12 ) 13 14 // ErrIncorrectResponseType a form value for response_type was not set to token or code 15 var ErrIncorrectResponseType = errors.New("Response type not one of token or code") 16 17 func (s *Service) authorizeForm(w http.ResponseWriter, r *http.Request) { 18 sessionService, client, _, responseType, _, err := s.authorizeCommon(r) 19 if err != nil { 20 http.Error(w, err.Error(), http.StatusBadRequest) 21 return 22 } 23 24 // Render the template 25 errMsg, _ := sessionService.GetFlashMessage() 26 query := r.URL.Query() 27 query.Set("login_redirect_uri", r.URL.Path) 28 renderTemplate(w, "authorize.html", map[string]interface{}{ 29 "error": errMsg, 30 "clientID": client.Key, 31 "queryString": getQueryString(query), 32 "token": responseType == "token", 33 }) 34 } 35 36 func (s *Service) authorize(w http.ResponseWriter, r *http.Request) { 37 _, client, user, responseType, redirectURI, err := s.authorizeCommon(r) 38 if err != nil { 39 http.Error(w, err.Error(), http.StatusBadRequest) 40 return 41 } 42 43 // Get the state parameter 44 state := r.Form.Get("state") 45 46 // Has the resource owner or authorization server denied the request? 47 authorized := len(r.Form.Get("allow")) > 0 48 if !authorized { 49 errorRedirect(w, r, redirectURI, "access_denied", state, responseType) 50 return 51 } 52 53 // Check the requested scope 54 scope, err := s.oauthService.GetScope(r.Form.Get("scope")) 55 if err != nil { 56 errorRedirect(w, r, redirectURI, "invalid_scope", state, responseType) 57 return 58 } 59 60 query := redirectURI.Query() 61 62 // When response_type == "code", we will grant an authorization code 63 if responseType == "code" { 64 // Create a new authorization code 65 authorizationCode, err := s.oauthService.GrantAuthorizationCode( 66 client, // client 67 user, // user 68 s.cnf.Oauth.AuthCodeLifetime, // expires in 69 redirectURI.String(), // redirect URI 70 scope, // scope 71 ) 72 if err != nil { 73 errorRedirect(w, r, redirectURI, "server_error", state, responseType) 74 return 75 } 76 77 // Set query string params for the redirection URL 78 query.Set("code", authorizationCode.Code) 79 // Add state param if present (recommended) 80 if state != "" { 81 query.Set("state", state) 82 } 83 // And we're done here, redirect 84 redirectWithQueryString(redirectURI.String(), query, w, r) 85 return 86 } 87 88 // When response_type == "token", we will directly grant an access token 89 if responseType == "token" { 90 // Get access token lifetime from user input 91 lifetime, err := strconv.Atoi(r.Form.Get("lifetime")) 92 if err != nil { 93 errorRedirect(w, r, redirectURI, "server_error", state, responseType) 94 return 95 } 96 97 // Grant an access token 98 accessToken, err := s.oauthService.GrantAccessToken( 99 client, // client 100 user, // user 101 lifetime, // expires in 102 scope, // scope 103 ) 104 if err != nil { 105 errorRedirect(w, r, redirectURI, "server_error", state, responseType) 106 return 107 } 108 109 // Set query string params for the redirection URL 110 query.Set("access_token", accessToken.Token) 111 query.Set("expires_in", fmt.Sprintf("%d", s.cnf.Oauth.AccessTokenLifetime)) 112 query.Set("token_type", "Bearer") 113 query.Set("scope", scope) 114 // Add state param if present (recommended) 115 if state != "" { 116 query.Set("state", state) 117 } 118 // And we're done here, redirect 119 redirectWithFragment(redirectURI.String(), query, w, r) 120 } 121 } 122 123 func (s *Service) authorizeCommon(r *http.Request) (session.ServiceInterface, *models.OauthClient, *models.OauthUser, string, *url.URL, error) { 124 // Get the session service from the request context 125 sessionService, err := getSessionService(r) 126 if err != nil { 127 return nil, nil, nil, "", nil, err 128 } 129 130 // Get the client from the request context 131 client, err := getClient(r) 132 if err != nil { 133 return nil, nil, nil, "", nil, err 134 } 135 136 // Get the user session 137 userSession, err := sessionService.GetUserSession() 138 if err != nil { 139 return nil, nil, nil, "", nil, err 140 } 141 142 // Fetch the user 143 user, err := s.oauthService.FindUserByUsername( 144 userSession.Username, 145 ) 146 if err != nil { 147 return nil, nil, nil, "", nil, err 148 } 149 150 // Check the response_type is either "code" or "token" 151 responseType := r.Form.Get("response_type") 152 if responseType != "code" && responseType != "token" { 153 return nil, nil, nil, "", nil, ErrIncorrectResponseType 154 } 155 156 // Fallback to the client redirect URI if not in query string 157 redirectURI := r.Form.Get("redirect_uri") 158 if redirectURI == "" { 159 redirectURI = client.RedirectURI.String 160 } 161 162 // // Parse the redirect URL 163 parsedRedirectURI, err := url.ParseRequestURI(redirectURI) 164 if err != nil { 165 return nil, nil, nil, "", nil, err 166 } 167 168 return sessionService, client, user, responseType, parsedRedirectURI, nil 169 }