| 110 | } |
| 111 | |
| 112 | func (a *API) maybeLoadUserOrSession(ctx context.Context) (context.Context, error) { |
| 113 | db := a.db.WithContext(ctx) |
| 114 | claims := getClaims(ctx) |
| 115 | |
| 116 | if claims == nil { |
| 117 | return ctx, apierrors.NewForbiddenError(apierrors.ErrorCodeBadJWT, "invalid token: missing claims") |
| 118 | } |
| 119 | |
| 120 | if claims.Subject == "" { |
| 121 | return nil, apierrors.NewForbiddenError(apierrors.ErrorCodeBadJWT, "invalid claim: missing sub claim") |
| 122 | } |
| 123 | |
| 124 | var user *models.User |
| 125 | if claims.Subject != "" { |
| 126 | userId, err := uuid.FromString(claims.Subject) |
| 127 | if err != nil { |
| 128 | return ctx, apierrors.NewBadRequestError(apierrors.ErrorCodeBadJWT, "invalid claim: sub claim must be a UUID").WithInternalError(err) |
| 129 | } |
| 130 | user, err = models.FindUserByID(db, userId) |
| 131 | if err != nil { |
| 132 | if models.IsNotFoundError(err) { |
| 133 | return ctx, apierrors.NewForbiddenError(apierrors.ErrorCodeUserNotFound, "User from sub claim in JWT does not exist") |
| 134 | } |
| 135 | return ctx, err |
| 136 | } |
| 137 | ctx = withUser(ctx, user) |
| 138 | } |
| 139 | |
| 140 | var session *models.Session |
| 141 | if claims.SessionId != "" && claims.SessionId != uuid.Nil.String() { |
| 142 | sessionId, err := uuid.FromString(claims.SessionId) |
| 143 | if err != nil { |
| 144 | return ctx, apierrors.NewForbiddenError(apierrors.ErrorCodeBadJWT, "invalid claim: session_id claim must be a UUID").WithInternalError(err) |
| 145 | } |
| 146 | session, err = models.FindSessionByID(db, sessionId, false) |
| 147 | if err != nil { |
| 148 | if models.IsNotFoundError(err) { |
| 149 | return ctx, apierrors.NewForbiddenError(apierrors.ErrorCodeSessionNotFound, "Session from session_id claim in JWT does not exist").WithInternalError(err).WithInternalMessage("session id (%s) doesn't exist", sessionId) |
| 150 | } |
| 151 | return ctx, err |
| 152 | } |
| 153 | ctx = withSession(ctx, session) |
| 154 | // Also store in shared context for cross-package access (e.g., oauthserver package) |
| 155 | ctx = shared.WithSession(ctx, session) |
| 156 | } |
| 157 | return ctx, nil |
| 158 | } |