handle response mode

This commit is contained in:
Livio Amstutz 2021-10-25 11:57:26 +02:00
parent f067d723f2
commit 484182a0f8
5 changed files with 49 additions and 15 deletions

View file

@ -32,6 +32,7 @@ func NewAuthStorage() op.Storage {
type AuthRequest struct {
ID string
ResponseType oidc.ResponseType
ResponseMode oidc.ResponseMode
RedirectURI string
Nonce string
ClientID string
@ -87,6 +88,10 @@ func (a *AuthRequest) GetResponseType() oidc.ResponseType {
return a.ResponseType
}
func (a *AuthRequest) GetResponseMode() oidc.ResponseMode {
return a.ResponseMode
}
func (a *AuthRequest) GetScopes() []string {
return []string{
"openid",

View file

@ -42,6 +42,9 @@ const (
DisplayTouch Display = "touch"
DisplayWAP Display = "wap"
ResponseModeQuery ResponseMode = "query"
ResponseModeFragment ResponseMode = "fragment"
//PromptNone (`none`) disallows the Authorization Server to display any authentication or consent user interface pages.
//An error (login_required, interaction_required, ...) will be returned if the user is not already authenticated or consent is needed
PromptNone = "none"

View file

@ -67,6 +67,8 @@ type Prompt SpaceDelimitedArray
type ResponseType string
type ResponseMode string
func (s SpaceDelimitedArray) Encode() string {
return strings.Join(s, " ")
}

View file

@ -26,6 +26,7 @@ type AuthRequest interface {
GetNonce() string
GetRedirectURI() string
GetResponseType() oidc.ResponseType
GetResponseMode() oidc.ResponseMode
GetScopes() []string
GetState() string
GetSubject() string
@ -413,9 +414,17 @@ func AuthResponseCode(w http.ResponseWriter, r *http.Request, authReq AuthReques
AuthRequestError(w, r, authReq, err, authorizer.Encoder())
return
}
callback := fmt.Sprintf("%s?code=%s", authReq.GetRedirectURI(), code)
if authReq.GetState() != "" {
callback = callback + "&state=" + authReq.GetState()
codeResponse := struct {
Code string
State string
}{
Code: code,
State: authReq.GetState(),
}
callback, err := AuthResponseURL(authReq.GetRedirectURI(), authReq.GetResponseType(), authReq.GetResponseMode(), &codeResponse, authorizer.Encoder())
if err != nil {
AuthRequestError(w, r, authReq, err, authorizer.Encoder())
return
}
http.Redirect(w, r, callback, http.StatusFound)
}
@ -428,12 +437,11 @@ func AuthResponseToken(w http.ResponseWriter, r *http.Request, authReq AuthReque
AuthRequestError(w, r, authReq, err, authorizer.Encoder())
return
}
params, err := httphelper.URLEncodeResponse(resp, authorizer.Encoder())
callback, err := AuthResponseURL(authReq.GetRedirectURI(), authReq.GetResponseType(), authReq.GetResponseMode(), resp, authorizer.Encoder())
if err != nil {
AuthRequestError(w, r, authReq, err, authorizer.Encoder())
return
}
callback := fmt.Sprintf("%s#%s", authReq.GetRedirectURI(), params)
http.Redirect(w, r, callback, http.StatusFound)
}
@ -453,3 +461,22 @@ func CreateAuthRequestCode(ctx context.Context, authReq AuthRequest, storage Sto
func BuildAuthRequestCode(authReq AuthRequest, crypto Crypto) (string, error) {
return crypto.Encrypt(authReq.GetID())
}
//AuthResponseURL encodes the authorization response (successful and error) and sets it as query or fragment values
//depending on the response_mode and response_type
func AuthResponseURL(redirectURI string, responseType oidc.ResponseType, responseMode oidc.ResponseMode, response interface{}, encoder httphelper.Encoder) (string, error) {
params, err := httphelper.URLEncodeResponse(response, encoder)
if err != nil {
return "", err
}
if responseMode == oidc.ResponseModeQuery {
return redirectURI + "?" + params, nil
}
if responseMode == oidc.ResponseModeFragment {
return redirectURI + "#" + params, nil
}
if responseType == "" || responseType == oidc.ResponseTypeCode {
return redirectURI + "?" + params, nil
}
return redirectURI + "#" + params, nil
}

View file

@ -19,23 +19,20 @@ func AuthRequestError(w http.ResponseWriter, r *http.Request, authReq ErrAuthReq
return
}
e := oidc.DefaultToServerError(err, err.Error()) //TODO: desc?
e.State = authReq.GetState()
if authReq.GetRedirectURI() == "" || e.IsRedirectDisabled() {
if authReq == nil || authReq.GetRedirectURI() == "" || e.IsRedirectDisabled() {
http.Error(w, e.Description, http.StatusBadRequest)
return
}
params, err := httphelper.URLEncodeResponse(e, encoder)
e.State = authReq.GetState()
var responseMode oidc.ResponseMode
if rm, ok := authReq.(interface{ GetResponseMode() oidc.ResponseMode }); ok {
responseMode = rm.GetResponseMode()
}
url, err := AuthResponseURL(authReq.GetRedirectURI(), authReq.GetResponseType(), responseMode, e, encoder)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
url := authReq.GetRedirectURI()
responseType := authReq.GetResponseType()
if responseType == "" || responseType == oidc.ResponseTypeCode {
url += "?" + params
} else {
url += "#" + params
}
http.Redirect(w, r, url, http.StatusFound)
}