diff --git a/consts/redis_key.go b/consts/redis_key.go index 1b82715..e7fb534 100644 --- a/consts/redis_key.go +++ b/consts/redis_key.go @@ -1,8 +1,8 @@ package consts const ( - REDIS_KEY_LOGIN_SESSION = "misso:login:%s" // Username, token as value - REDIS_KEY_CONSENT_CSRF = "misso:consent:%s" // Random string, consent challenge as value - REDIS_KEY_SHARE_ACCESS_TOKEN = "misso:share:at:%s" // Subject, access token as value - REDIS_KEY_SHARE_USER_INFO = "misso:share:ui:%s" // Subject, user info as value + REDIS_KEY_LOGIN_SESSION = "misso:login:%s" // Username, token as value + REDIS_KEY_CONSENT_CSRF = "misso:consent:%s" // Random string, consent challenge as value + REDIS_KEY_USER_ACCESS_TOKEN = "misso:user:token:%s" // Subject, access token as value + REDIS_KEY_USER_INFO = "misso:user:info:%s" // Subject, user info as value ) diff --git a/consts/time.go b/consts/time.go index 25dbb44..309757e 100644 --- a/consts/time.go +++ b/consts/time.go @@ -5,8 +5,8 @@ import "time" const ( TIME_REQUEST_VALID = 1 * time.Hour - TIME_LOGIN_REMEMBER = 10 * time.Minute + TIME_LOGIN_REMEMBER = 10 * time.Minute TIME_CONSENT_REMEMBER = 0 // Forever - TIME_USERINFO_CACHE = 10 * time.Minute + TIME_USERINFO_CACHE = 1 * time.Hour ) diff --git a/handlers/consent/consent_check.go b/handlers/consent/consent_check.go index 7503f44..6b8c027 100644 --- a/handlers/consent/consent_check.go +++ b/handlers/consent/consent_check.go @@ -56,8 +56,8 @@ func ConsentCheck(ctx *gin.Context) { // Generate CSRF token global.Logger.Debugf("Generating CSRF token...") csrf := utils.RandString(32) - sessKey := fmt.Sprintf(consts.REDIS_KEY_CONSENT_CSRF, csrf) - err := global.Redis.Set(context.Background(), sessKey, oauth2challenge, consts.TIME_REQUEST_VALID).Err() + sessKey := fmt.Sprintf(consts.REDIS_KEY_CONSENT_CSRF, oauth2challenge) + err := global.Redis.Set(context.Background(), sessKey, csrf, consts.TIME_REQUEST_VALID).Err() if err != nil { global.Logger.Errorf("Failed to save csrf into redis with error: %v", err) ctx.HTML(http.StatusInternalServerError, "error.tmpl", gin.H{ @@ -69,7 +69,7 @@ func ConsentCheck(ctx *gin.Context) { // Retrieve context global.Logger.Debugf("Retrieving context...") - userinfoCtx, err := utils.GetUserinfo(*consentReq.Subject) + userinfo, err := utils.GetUserinfo(*consentReq.Subject) if err != nil { global.Logger.Errorf("Failed to retrieve userinfo with error: %v", err) ctx.HTML(http.StatusInternalServerError, "error.tmpl", gin.H{ @@ -81,9 +81,10 @@ func ConsentCheck(ctx *gin.Context) { // Show the consent UI global.Logger.Debugf("Rendering consent UI...") templateFields := gin.H{ - "user": *userinfoCtx, + "user": *userinfo, "challenge": oauth2challenge, "csrf": csrf, + "scopes": consentReq.RequestedScope, } if consentReq.Client.LogoUri != nil && *consentReq.Client.LogoUri != "" { @@ -94,6 +95,12 @@ func ConsentCheck(ctx *gin.Context) { } else { templateFields["clientName"] = *consentReq.Client.ClientId } + if consentReq.Client.PolicyUri != nil && *consentReq.Client.PolicyUri != "" { + templateFields["clientPolicy"] = *consentReq.Client.PolicyUri + } + if consentReq.Client.TosUri != nil && *consentReq.Client.TosUri != "" { + templateFields["clientTos"] = *consentReq.Client.TosUri + } ctx.HTML(http.StatusOK, "consent.tmpl", templateFields) global.Logger.Debugf("User should now see Consent UI.") diff --git a/handlers/consent/consent_confirm.go b/handlers/consent/consent_confirm.go index d93055d..63e06d8 100644 --- a/handlers/consent/consent_confirm.go +++ b/handlers/consent/consent_confirm.go @@ -12,9 +12,10 @@ import ( ) type ConsentConfirmRequest struct { - CSRF string `form:"_csrf"` - Remember bool `form:"remember"` - Action string `form:"action"` + CSRF string `form:"_csrf"` + Challenge string `form:"challenge"` + Remember bool `form:"remember"` + Action string `form:"action"` } func ConsentConfirm(ctx *gin.Context) { @@ -32,16 +33,23 @@ func ConsentConfirm(ctx *gin.Context) { // 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() + sessKey := fmt.Sprintf(consts.REDIS_KEY_CONSENT_CSRF, req.Challenge) + csrfSession, 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 + } else if csrfSession != req.CSRF { + ctx.HTML(http.StatusForbidden, "error.tmpl", gin.H{ + "error": "CSRF not match", + }) + return } + oauth2challenge := req.Challenge + // Delete used challenge global.Redis.Del(context.Background(), sessKey) diff --git a/handlers/login/misskey_auth_callback.go b/handlers/login/misskey_auth_callback.go index bdfc35a..05635b5 100644 --- a/handlers/login/misskey_auth_callback.go +++ b/handlers/login/misskey_auth_callback.go @@ -9,7 +9,6 @@ import ( "misso/consts" "misso/global" "misso/misskey" - "misso/utils" "net/http" "time" ) @@ -62,9 +61,10 @@ func MisskeyAuthCallback(ctx *gin.Context) { return } - userid := fmt.Sprintf("%s@%s", usermeta.User.Username, config.Config.Misskey.Instance) + // Save user key + userIdentifier := fmt.Sprintf("%s@%s", usermeta.User.Username, config.Config.Misskey.Instance) - sessAccessTokenKey := fmt.Sprintf(consts.REDIS_KEY_SHARE_ACCESS_TOKEN, userid) + sessAccessTokenKey := fmt.Sprintf(consts.REDIS_KEY_USER_ACCESS_TOKEN, userIdentifier) err = global.Redis.Set(context.Background(), sessAccessTokenKey, usermeta.AccessToken, 0).Err() if err != nil { global.Logger.Errorf("Failed to save session access token into redis with error: %v", err) @@ -74,21 +74,11 @@ func MisskeyAuthCallback(ctx *gin.Context) { return } - // Save context into redis - err = utils.SaveUserinfo(userid, &usermeta.User) - if err != nil { - global.Logger.Errorf("Failed to save session user info into redis with error: %v", err) - ctx.HTML(http.StatusInternalServerError, "error.tmpl", gin.H{ - "error": "Failed to save userinfo", - }) - return - } - global.Logger.Debugf("User accepted the request, reporting back to hydra...") remember := true rememberFor := int64(consts.TIME_LOGIN_REMEMBER / time.Second) acceptReq, _, err := global.Hydra.Admin.OAuth2Api.AcceptOAuth2LoginRequest(context.Background()).LoginChallenge(oauth2challenge).AcceptOAuth2LoginRequest(client.AcceptOAuth2LoginRequest{ - Subject: userid, + Subject: userIdentifier, Remember: &remember, RememberFor: &rememberFor, }).Execute() diff --git a/handlers/user/info.go b/handlers/user/info.go index a318dc4..a74c96f 100644 --- a/handlers/user/info.go +++ b/handlers/user/info.go @@ -4,17 +4,11 @@ import ( "context" "github.com/gin-gonic/gin" "misso/global" - "misso/types" "misso/utils" "net/http" "strings" ) -type UserinfoResponse struct { - types.MisskeyUser - EMail string `json:"email"` -} - func UserInfo(ctx *gin.Context) { // Get token from header accessToken := strings.Replace(ctx.GetHeader("Authorization"), "Bearer ", "", 1) @@ -45,7 +39,7 @@ func UserInfo(ctx *gin.Context) { // Return user info global.Logger.Debugf("Retrieving context...") - userinfoCtx, err := utils.GetUserinfo(*tokenInfo.Sub) + userinfo, err := utils.GetUserinfo(*tokenInfo.Sub) if err != nil { global.Logger.Errorf("Failed to retrieve userinfo with error: %v", err) ctx.HTML(http.StatusInternalServerError, "error.tmpl", gin.H{ @@ -54,9 +48,19 @@ func UserInfo(ctx *gin.Context) { return } - ctx.JSON(http.StatusOK, UserinfoResponse{ - MisskeyUser: *userinfoCtx, - EMail: *tokenInfo.Sub, - }) + userinfoRes := gin.H{} // map[string]interface{} + + // Get scopes + if tokenInfo.Scope != nil && *tokenInfo.Scope != "" { + // Has scopes + scopes := strings.Split(*tokenInfo.Scope, " ") + for _, s := range scopes { + if value, ok := (*userinfo)[s]; ok { + userinfoRes[s] = value + } + } + } + + ctx.JSON(http.StatusOK, userinfoRes) } diff --git a/misskey/get_userkey.go b/misskey/get_userkey.go index a1befd1..3e00f84 100644 --- a/misskey/get_userkey.go +++ b/misskey/get_userkey.go @@ -11,8 +11,8 @@ type AuthSessionUserkey_Request struct { } type AuthSessionUserkey_Response struct { - AccessToken string `json:"accessToken"` - User types.MisskeyUser `json:"user"` + AccessToken string `json:"accessToken"` + User types.MisskeyUserBase `json:"user"` } func GetUserkey(token string) (*AuthSessionUserkey_Response, error) { diff --git a/templates/consent.tmpl b/templates/consent.tmpl index 6e6c878..c7c9349 100644 --- a/templates/consent.tmpl +++ b/templates/consent.tmpl @@ -1,11 +1,58 @@ {{ define "consent.tmpl" }} - +