Commit 8aa06bcf authored by SlevinWasAlreadyTaken's avatar SlevinWasAlreadyTaken
Browse files

feat(auth): handle code_verifer for PKCE

parent 5d1bd328
......@@ -27,9 +27,10 @@ type CodeFlowParams struct {
// TokenFlowParams is used as parameter for token flow request
// it is built from query parameters
type TokenFlowParams struct {
Code string
Scopes []string
State string
Code string
Scopes []string
State string
CodeVerifier string
}
// TokenError represents the body error returned by the authorization server following https://tools.ietf.org/html/rfc6749#section-5.2
......@@ -115,39 +116,45 @@ func (acf *AuthorizationCodeFlow) RequestCode(w http.ResponseWriter, r *http.Req
// ExchangeToken : Native Go controller that redirect the user's agent with an access token if successful
func (acf *AuthorizationCodeFlow) ExchangeToken(w http.ResponseWriter, r *http.Request) {
code := r.URL.Query().Get("code")
// check code parameter - code should not be empty
if code == "" {
errCode := merror.MissingParameter
errDesc := "code"
// if an error has been specified by the auth server, use it
authErr := r.URL.Query().Get("error")
if authErr != "" {
errCode = merror.Code(authErr)
errDesc = r.URL.Query().Get("error_debug")
if errDesc == "" {
errDesc = r.URL.Query().Get("error_hint")
}
// if an error has been transmistted, use it
authErr := r.URL.Query().Get("error")
if authErr != "" {
errCode := merror.Code(authErr)
errDesc := r.URL.Query().Get("error_debug")
if errDesc == "" {
errDesc = r.URL.Query().Get("error_hint")
}
acf.redirectErr(w, errCode.String(), errDesc)
return
}
// check code parameter - it shall not be empty
code := r.URL.Query().Get("code")
if code == "" {
acf.redirectErr(w, merror.MissingParameter.String(), "code")
return
}
state := r.URL.Query().Get("state")
// check state parameter - state should not be empty
// check state parameter - it shall not be empty
if len(state) == 0 {
acf.redirectErr(w, merror.MissingParameter.String(), "state")
return
}
// check code verifier parameter - it can be empty
// TODO: make it mandatory when frontend uses it
codeVerifier := r.URL.Query().Get("code_verifier")
// scope is allowed to be empty
scope := r.URL.Query().Get("scope")
// get access token URL
params := TokenFlowParams{
Code: code,
State: state,
Scopes: fromSpacedSep(scope),
Code: code,
CodeVerifier: codeVerifier,
State: state,
Scopes: fromSpacedSep(scope),
}
redirectUrl, err := acf.GetURLWithAccessToken(r.Context(), params)
if err != nil {
......@@ -225,7 +232,12 @@ func (acf *AuthorizationCodeFlow) GetURLWithAccessToken(ctx context.Context, par
Scopes: params.Scopes,
}
token, err := config.Exchange(ctx, params.Code)
opts := []oauth2.AuthCodeOption{}
if params.CodeVerifier != "" {
opts = append(opts, oauth2.SetAuthURLParam("code_verifier", params.CodeVerifier))
}
token, err := config.Exchange(ctx, params.Code, opts...)
if err != nil {
return nil, err
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment