github.com/wanliu/go-oauth2-server@v0.0.0-20180817021415-f928fa1580df/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/wanliu/go-oauth2-server/models" 11 "github.com/wanliu/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 "clientName": client.Name, 32 "queryString": getQueryString(query), 33 "token": responseType == "token", 34 }) 35 } 36 37 func (s *Service) authorize(w http.ResponseWriter, r *http.Request) { 38 _, client, user, responseType, redirectURI, err := s.authorizeCommon(r) 39 if err != nil { 40 http.Error(w, err.Error(), http.StatusBadRequest) 41 return 42 } 43 44 // Get the state parameter 45 state := r.Form.Get("state") 46 47 // Has the resource owner or authorization server denied the request? 48 authorized := len(r.Form.Get("allow")) > 0 49 if !authorized { 50 errorRedirect(w, r, redirectURI, "access_denied", state, responseType) 51 return 52 } 53 54 // Check the requested scope 55 scope, err := s.oauthService.GetScope(r.Form.Get("scope")) 56 if err != nil { 57 errorRedirect(w, r, redirectURI, "invalid_scope", state, responseType) 58 return 59 } 60 61 query := redirectURI.Query() 62 63 // When response_type == "code", we will grant an authorization code 64 if responseType == "code" { 65 // Create a new authorization code 66 authorizationCode, err := s.oauthService.GrantAuthorizationCode( 67 client, // client 68 user, // user 69 s.cnf.Oauth.AuthCodeLifetime, // expires in 70 redirectURI.String(), // redirect URI 71 scope, // scope 72 ) 73 if err != nil { 74 errorRedirect(w, r, redirectURI, "server_error", state, responseType) 75 return 76 } 77 78 // Set query string params for the redirection URL 79 query.Set("code", authorizationCode.Code) 80 // Add state param if present (recommended) 81 if state != "" { 82 query.Set("state", state) 83 } 84 // And we're done here, redirect 85 redirectWithQueryString(redirectURI.String(), query, w, r) 86 return 87 } 88 89 // When response_type == "token", we will directly grant an access token 90 if responseType == "token" { 91 // Get access token lifetime from user input 92 lifetime, err := strconv.Atoi(r.Form.Get("lifetime")) 93 if err != nil { 94 errorRedirect(w, r, redirectURI, "server_error", state, responseType) 95 return 96 } 97 98 // Grant an access token 99 accessToken, err := s.oauthService.GrantAccessToken( 100 client, // client 101 user, // user 102 lifetime, // expires in 103 scope, // scope 104 ) 105 if err != nil { 106 errorRedirect(w, r, redirectURI, "server_error", state, responseType) 107 return 108 } 109 110 // Set query string params for the redirection URL 111 query.Set("access_token", accessToken.Token) 112 query.Set("expires_in", fmt.Sprintf("%d", s.cnf.Oauth.AccessTokenLifetime)) 113 query.Set("token_type", "Bearer") 114 query.Set("scope", scope) 115 // Add state param if present (recommended) 116 if state != "" { 117 query.Set("state", state) 118 } 119 // And we're done here, redirect 120 redirectWithFragment(redirectURI.String(), query, w, r) 121 } 122 } 123 124 func (s *Service) authorizeCommon(r *http.Request) (session.ServiceInterface, *models.OauthClient, *models.OauthUser, string, *url.URL, error) { 125 // Get the session service from the request context 126 sessionService, err := getSessionService(r) 127 if err != nil { 128 return nil, nil, nil, "", nil, err 129 } 130 131 // Get the client from the request context 132 client, err := getClient(r) 133 if err != nil { 134 return nil, nil, nil, "", nil, err 135 } 136 137 // Get the user session 138 userSession, err := sessionService.GetUserSession() 139 if err != nil { 140 return nil, nil, nil, "", nil, err 141 } 142 143 // Fetch the user 144 user, err := s.oauthService.FindUserByUsername( 145 userSession.Username, 146 ) 147 if err != nil { 148 return nil, nil, nil, "", nil, err 149 } 150 151 // Check the response_type is either "code" or "token" 152 responseType := r.Form.Get("response_type") 153 if responseType != "code" && responseType != "token" { 154 return nil, nil, nil, "", nil, ErrIncorrectResponseType 155 } 156 157 // Fallback to the client redirect URI if not in query string 158 redirectURI := r.Form.Get("redirect_uri") 159 if redirectURI == "" { 160 redirectURI = client.RedirectURI.String 161 } 162 163 // // Parse the redirect URL 164 parsedRedirectURI, err := url.ParseRequestURI(redirectURI) 165 if err != nil { 166 return nil, nil, nil, "", nil, err 167 } 168 169 return sessionService, client, user, responseType, parsedRedirectURI, nil 170 }