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  }