update
This commit is contained in:
@@ -22,8 +22,8 @@ OAUTH2_SCOPES_SUPPORTED = os.getenv('OAUTH2_SCOPES_SUPPORTED')
|
||||
|
||||
|
||||
GRANT_TYPES_EXPIRES_IN = {
|
||||
'refresh_token': 900,
|
||||
'authorization_code': 900,
|
||||
'refresh_token': 600,
|
||||
'authorization_code': 600,
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
from authlib.oauth2 import ResourceProtector as _ResourceProtector
|
||||
|
||||
|
||||
class ResourceProtector(_ResourceProtector): ...
|
||||
@@ -1,8 +1,12 @@
|
||||
import re
|
||||
|
||||
from authlib.oauth2 import OAuth2Request
|
||||
from authlib.oauth2.rfc6749 import ClientMixin, TokenMixin, grants
|
||||
from authlib.oauth2.rfc7636 import CodeChallenge
|
||||
from authlib.oidc.core import OpenIDCode as OpenIDCode_
|
||||
from authlib.oidc.core import UserInfo
|
||||
from aws_lambda_powertools import Logger
|
||||
from aws_lambda_powertools.event_handler.exceptions import NotFoundError
|
||||
from layercake.dateutils import now, ttl
|
||||
from layercake.dynamodb import DynamoDBPersistenceLayer, KeyPair
|
||||
from layercake.funcs import omit, pick
|
||||
@@ -17,6 +21,7 @@ from integrations.apigateway_oauth2.tokens import (
|
||||
OAuth2Token,
|
||||
)
|
||||
|
||||
logger = Logger(__name__)
|
||||
oauth2_layer = DynamoDBPersistenceLayer(OAUTH2_TABLE, dynamodb_client)
|
||||
|
||||
|
||||
@@ -137,22 +142,30 @@ class AuthorizationCodeGrant(grants.AuthorizationCodeGrant):
|
||||
return pick(('id', 'name', 'email', 'email_verified'), user)
|
||||
|
||||
|
||||
class RefreshTokenNotFoundError(NotFoundError):
|
||||
def __init__(self, *_):
|
||||
super().__init__('Refresh token not found')
|
||||
|
||||
|
||||
class RefreshTokenGrant(grants.RefreshTokenGrant):
|
||||
INCLUDE_NEW_REFRESH_TOKEN = True
|
||||
TOKEN_ENDPOINT_AUTH_METHODS = [
|
||||
'client_secret_basic',
|
||||
'client_secret_post',
|
||||
'none',
|
||||
]
|
||||
INCLUDE_NEW_REFRESH_TOKEN = True
|
||||
|
||||
def authenticate_refresh_token(self, refresh_token: str, **kwargs) -> TokenMixin:
|
||||
token = oauth2_layer.get_item(
|
||||
token = oauth2_layer.collection.get_item(
|
||||
KeyPair(
|
||||
pk='OAUTH2#TOKEN',
|
||||
sk=f'REFRESH_TOKEN#{refresh_token}',
|
||||
)
|
||||
),
|
||||
exc_cls=RefreshTokenNotFoundError,
|
||||
)
|
||||
|
||||
logger.info('Refresh token retrieved', token=token)
|
||||
|
||||
return OAuth2Token(
|
||||
expires_in=int(token['expires_in']),
|
||||
issued_at=int(token['issued_at']),
|
||||
@@ -164,7 +177,10 @@ class RefreshTokenGrant(grants.RefreshTokenGrant):
|
||||
return refresh_token.get_user()
|
||||
|
||||
def revoke_old_credential(self, refresh_token: TokenMixin) -> None:
|
||||
if token := getattr(refresh_token, 'refresh_token', None):
|
||||
logger.info('Revoking old refresh token', refresh_token=refresh_token)
|
||||
token = getattr(refresh_token, 'refresh_token', None)
|
||||
|
||||
if token:
|
||||
oauth2_layer.delete_item(
|
||||
KeyPair(pk='OAUTH2#TOKEN', sk=f'REFRESH_TOKEN#{token}')
|
||||
)
|
||||
|
||||
@@ -3,6 +3,6 @@ from aws_lambda_powertools.event_handler.api_gateway import Router
|
||||
router = Router()
|
||||
|
||||
|
||||
@router.get('/jwks.json')
|
||||
@router.get('/.well-known/jwks.json')
|
||||
def jwks():
|
||||
return {}
|
||||
|
||||
@@ -5,4 +5,4 @@ router = Router()
|
||||
|
||||
@router.get('/userinfo')
|
||||
def userinfo():
|
||||
return {}
|
||||
return {'name': 'test'}
|
||||
|
||||
@@ -26,7 +26,7 @@ Globals:
|
||||
OAUTH2_TABLE: !Ref OAuth2Table
|
||||
ISSUER: https://id.saladeaula.digital
|
||||
JWT_SECRET: 7DUTFB1iLeSpiXvmxbOZim1yPVmQbmBpAzgscob0RDzrL2wVwRi1ti2ZSry7jJAf
|
||||
OAUTH2_SCOPES_SUPPORTED: openid profile email
|
||||
OAUTH2_SCOPES_SUPPORTED: openid profile email offline_access
|
||||
|
||||
Resources:
|
||||
HttpLog:
|
||||
@@ -79,7 +79,7 @@ Resources:
|
||||
Jwks:
|
||||
Type: HttpApi
|
||||
Properties:
|
||||
Path: /jwks.json
|
||||
Path: /.well-known/jwks.json
|
||||
Method: GET
|
||||
ApiId: !Ref HttpApi
|
||||
Token:
|
||||
|
||||
@@ -20,7 +20,7 @@ def pytest_configure():
|
||||
os.environ['JWT_SECRET'] = 'secret'
|
||||
os.environ['DYNAMODB_PARTITION_KEY'] = PK
|
||||
os.environ['DYNAMODB_SORT_KEY'] = SK
|
||||
os.environ['OAUTH2_SCOPES_SUPPORTED'] = 'openid profile email'
|
||||
os.environ['OAUTH2_SCOPES_SUPPORTED'] = 'openid profile email offline_access'
|
||||
# os.environ['POWERTOOLS_LOGGER_LOG_EVENT'] = 'true'
|
||||
|
||||
|
||||
|
||||
@@ -29,8 +29,9 @@ def test_authorize(
|
||||
'response_type': 'code',
|
||||
'client_id': client_id,
|
||||
'redirect_uri': 'https://localhost/callback',
|
||||
'scope': 'openid',
|
||||
'scope': 'openid offline_access',
|
||||
'nonce': '123',
|
||||
'state': '456',
|
||||
},
|
||||
cookies=[
|
||||
f'id_token={id_token}; HttpOnly; Secure',
|
||||
|
||||
@@ -38,7 +38,7 @@ def test_token(
|
||||
auth_token = json.loads(r['body'])
|
||||
|
||||
assert r['statusCode'] == HTTPStatus.OK
|
||||
assert auth_token['expires_in'] == 900
|
||||
assert auth_token['expires_in'] == 600
|
||||
|
||||
r = dynamodb_persistence_layer.query(
|
||||
key_cond_expr='#pk = :pk',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// OAuth2
|
||||
{"id": "OAUTH2", "sk": "CLIENT_ID#d72d4005-1fa7-4430-9754-80d5e2487bb6", "client_secret": "1nFD8alDbGHgc3g1RLY960xyRJVee0SlMoIB0MUlSuiJy28W", "name": "pytest", "scope": "openid profile", "redirect_uris": ["https://localhost/callback"], "response_types": ["code"], "grant_types": ["authorization_code", "refresh_token"], "scope": "openid profile email", "token_endpoint_auth_method": "none"}
|
||||
{"id": "OAUTH2", "sk": "CLIENT_ID#d72d4005-1fa7-4430-9754-80d5e2487bb6", "client_secret": "1nFD8alDbGHgc3g1RLY960xyRJVee0SlMoIB0MUlSuiJy28W", "name": "pytest", "scope": "openid profile", "redirect_uris": ["https://localhost/callback"], "response_types": ["code"], "grant_types": ["authorization_code", "refresh_token"], "scope": "openid profile email offline_access", "token_endpoint_auth_method": "none"}
|
||||
{"id": "OAUTH2#CODE", "sk": "CODE#kyqp3oSuRFTfuBaCmq3XOgGWg67l42Kt3D6xPEj7Yd3MLdi9", "client_id": "d72d4005-1fa7-4430-9754-80d5e2487bb6", "redirect_uri": "https://localhost/callback", "user_id": "357db1c5-7442-4075-98a3-fbe5c938a419", "nonce": null, "scope": "openid profile email", "response_type": "code", "code_challenge": "ejYEIGKQUgMnNh4eV0sftb0hXdLwkvKm6OHXRYvC--I", "code_challenge_method": "S256", "created_at": "2025-08-07T12:38:26.550431-03:00"}
|
||||
|
||||
// Post-migration: uncomment the following line
|
||||
|
||||
Reference in New Issue
Block a user