github.com/jxgolibs/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  }