misso/handlers/consent/consent_confirm.go

135 lines
4.4 KiB
Go

package consent
import (
"context"
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
client "github.com/ory/hydra-client-go/v2"
"misso/consts"
"misso/global"
"misso/types"
"net/http"
"time"
)
type ConsentConfirmRequest struct {
CSRF string `form:"_csrf"`
Remember bool `form:"remember"`
Action string `form:"action"`
}
func ConsentConfirm(ctx *gin.Context) {
// Parse request
global.Logger.Debugf("Parsing request...")
var req ConsentConfirmRequest
err := ctx.Bind(&req)
if err != nil {
ctx.HTML(http.StatusBadRequest, "error.tmpl", gin.H{
"error": "Failed to parse request",
})
return
}
// Validate CSRF
global.Logger.Debugf("Validating CSRF...")
sessKey := fmt.Sprintf(consts.REDIS_KEY_CONSENT_CSRF, req.CSRF)
oauth2challenge, err := global.Redis.Get(context.Background(), sessKey).Result()
if err != nil {
global.Logger.Errorf("Failed to get csrf from redis with error: %v", err)
ctx.HTML(http.StatusInternalServerError, "error.tmpl", gin.H{
"error": "Failed to get csrf",
})
return
}
// Delete used challenge
global.Redis.Del(context.Background(), sessKey)
// Get OAuth2 Client
global.Logger.Debugf("Getting OAuth2 Consent Request...")
consentReq, _, err := global.Hydra.Admin.OAuth2Api.GetOAuth2ConsentRequest(context.Background()).ConsentChallenge(oauth2challenge).Execute()
if err != nil {
global.Logger.Errorf("Failed to get required consent request with error: %v", err)
ctx.HTML(http.StatusInternalServerError, "error.tmpl", gin.H{
"error": "Failed to get required consent request",
})
return
}
// Check action type
if req.Action == "reject" {
global.Logger.Debugf("User rejected the request, reporting back to hydra...")
errId := "rejected_by_user"
errDesc := "The resource owner rejected the request"
rejectReq, _, err := global.Hydra.Admin.OAuth2Api.RejectOAuth2ConsentRequest(context.Background()).ConsentChallenge(oauth2challenge).RejectOAuth2Request(client.RejectOAuth2Request{
Error: &errId,
ErrorDescription: &errDesc,
}).Execute()
if err != nil {
global.Logger.Errorf("Failed to reject consent request with error: %v", err)
ctx.HTML(http.StatusInternalServerError, "error.tmpl", gin.H{
"error": "Failed to reject consent request",
})
return
}
ctx.Redirect(http.StatusTemporaryRedirect, rejectReq.RedirectTo)
global.Logger.Debugf("User should now be redirecting to target URI.")
} else if req.Action == "accept" {
global.Logger.Debugf("User accepted the request, reporting back to hydra...")
// Retrieve context
global.Logger.Debugf("Retrieving context...")
var acceptCtx types.SessionContext
sessKey = fmt.Sprintf(consts.REDIS_KEY_SHARE_CONTEXT, *consentReq.Subject)
acceptCtxBytes, err := global.Redis.Get(context.Background(), sessKey).Bytes()
if err != nil {
global.Logger.Errorf("Failed to retrieve context with error: %v", err)
ctx.HTML(http.StatusInternalServerError, "error.tmpl", gin.H{
"error": "Failed to retrieve context",
})
return
}
global.Logger.Debugf("Decoding context...")
err = json.Unmarshal(acceptCtxBytes, &acceptCtx)
if err != nil {
global.Logger.Errorf("Failed to parse context with error: %v", err)
ctx.HTML(http.StatusInternalServerError, "error.tmpl", gin.H{
"error": "Failed to parse context",
})
return
}
global.Logger.Debugf("Initializing ID Token...")
rememberFor := int64(consts.TIME_CONSENT_SESSION_VALID / time.Second)
acceptReq, _, err := global.Hydra.Admin.OAuth2Api.AcceptOAuth2ConsentRequest(context.Background()).ConsentChallenge(oauth2challenge).AcceptOAuth2ConsentRequest(client.AcceptOAuth2ConsentRequest{
GrantScope: consentReq.RequestedScope, // TODO: Specify scopes
GrantAccessTokenAudience: consentReq.RequestedAccessTokenAudience,
Remember: &req.Remember,
RememberFor: &rememberFor,
}).Execute()
if err != nil {
global.Logger.Errorf("Failed to accept consent request with error: %v", err)
ctx.HTML(http.StatusInternalServerError, "error.tmpl", gin.H{
"error": "Failed to accept consent request",
})
return
}
ctx.Redirect(http.StatusTemporaryRedirect, acceptReq.RedirectTo)
global.Logger.Debugf("User should now be redirecting to target URI.")
} else {
global.Logger.Errorf("Undefined consent action: %s", req.Action)
ctx.HTML(http.StatusBadRequest, "error.tmpl", gin.H{
"error": "Undefined consent action",
})
return
}
}