add scope to id

This commit is contained in:
2025-10-24 20:05:56 -03:00
parent c68aa98fc9
commit c4509f5072
18 changed files with 173 additions and 58 deletions

View File

@@ -9,14 +9,9 @@ OAUTH2_SCOPES_SUPPORTED: list[str] = [
'profile',
'email',
'offline_access',
'read:users',
'write:users',
'read:enrollments',
'write:enrollments',
'read:orders',
'write:orders',
'read:courses',
'write:courses',
'apps:admin',
'apps:studio',
'apps:insights',
]
SESSION_EXPIRES_IN = 86400 * 30 # 30 days

View File

@@ -1,4 +1,19 @@
from authlib.oauth2 import ResourceProtector as _ResourceProtector
from aws_lambda_powertools.event_handler import APIGatewayHttpResolver
from aws_lambda_powertools.event_handler.middlewares import NextMiddleware
from .requests import APIGatewayJsonRequest
class ResourceProtector(_ResourceProtector): ...
class ResourceProtector(_ResourceProtector):
def __call__(self, scopes=None, optional=False, **kwargs):
claims = kwargs
# backward compatibility
claims['scopes'] = scopes
def wrapper(app: APIGatewayHttpResolver, next_middleware: NextMiddleware):
request = APIGatewayJsonRequest(app.current_event)
print(request)
return next_middleware(app)
return wrapper

View File

@@ -1,5 +1,5 @@
import time
from dataclasses import dataclass
from dataclasses import dataclass, field
from authlib.oauth2.rfc6749 import (
AuthorizationCodeMixin,
@@ -15,6 +15,7 @@ class User:
name: str
email: str
email_verified: bool = False
scope: list[str] | None = None
def get_user_id(self):
return self.id

View File

@@ -1,3 +1,5 @@
from os import rename
from authlib.common.security import generate_token
from authlib.common.urls import add_params_to_uri
from authlib.jose import JsonWebKey
@@ -26,6 +28,7 @@ from config import ISSUER, OAUTH2_SCOPES_SUPPORTED, OAUTH2_TABLE
from integrations.apigateway_oauth2.authorization_server import (
AuthorizationServer,
)
from integrations.apigateway_oauth2.resource_protector import ResourceProtector
from integrations.apigateway_oauth2.tokens import (
OAuth2AuthorizationCode,
OAuth2Token,
@@ -65,15 +68,18 @@ class OpenIDCode(OpenIDCode_):
}
def generate_user_info(self, user: User, scope: str) -> UserInfo:
print(scope)
print('--' * 100)
return UserInfo(
user_info = UserInfo(
sub=user.id,
name=user.name,
email=user.email,
email_verified=user.email_verified,
).filter(scope)
if user.scope:
user_info['scope'] = ' '.join(user.scope)
return user_info
class AuthorizationCodeGrant(grants.AuthorizationCodeGrant):
TOKEN_ENDPOINT_AUTH_METHODS = [
@@ -166,20 +172,22 @@ class AuthorizationCodeGrant(grants.AuthorizationCodeGrant):
authorization_code: OAuth2AuthorizationCode,
) -> User:
"""Authenticate the user related to this authorization_code."""
user = dyn.get_item(
KeyPair(
pk=authorization_code.user_id,
sk='0',
),
user = dyn.collection.get_items(
TransactKey(authorization_code.user_id)
+ SortKey('0')
+ SortKey('SCOPE', path_spec='scope', rename_key='scope'),
)
return User(**pick(('id', 'name', 'email', 'email_verified'), user))
return User(**pick(('id', 'name', 'email', 'email_verified', 'scope'), user))
class TokenExchangeGrant(grants.BaseGrant):
GRANT_TYPE = 'urn:ietf:params:oauth:grant-type:token-exchange'
TOKEN_ENDPOINT_AUTH_METHODS = ['client_secret_basic', 'client_secret_post']
TOKEN_ENDPOINT_AUTH_METHODS = [
'client_secret_basic',
'client_secret_post',
]
@hooked
def validate_token_request(self):
@@ -288,6 +296,17 @@ class RevocationEndpoint(rfc7009.RevocationEndpoint):
token: OAuth2Token,
request: OAuth2Request,
):
"""
Mark token as revoked. Since token MUST be unique, it would be dangerous
to delete it. Consider this situation:
- Jane obtained a token XYZ
- Jane revoked (deleted) token XYZ
- Bob generated a new token XYZ
- Jane can use XYZ to access Bobs resource
- https://docs.authlib.org/en/latest/specs/rfc7009.html#authlib.oauth2.rfc7009.RevocationEndpoint.revoke_token
"""
user_id = token.user['id']
r = dyn.collection.query(KeyPair(pk=user_id, sk='SESSION'))
@@ -377,3 +396,5 @@ server.register_grant(TokenExchangeGrant)
server.register_grant(RefreshTokenGrant)
server.register_endpoint(RevocationEndpoint)
server.register_extension(IssuerParameter())
require_oauth = ResourceProtector()

View File

@@ -1,8 +1,10 @@
from aws_lambda_powertools.event_handler.api_gateway import Router
from oauth2 import require_oauth
router = Router()
@router.get('/userinfo')
@router.get('/userinfo', middlewares=[require_oauth('profile')])
def userinfo():
return {'name': 'test'}