update t p
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
from http import HTTPStatus
|
|
||||||
from http.cookies import SimpleCookie
|
from http.cookies import SimpleCookie
|
||||||
|
|
||||||
import jwt
|
import jwt
|
||||||
@@ -41,10 +40,9 @@ def authorize():
|
|||||||
client_scopes = set(scope_to_list(grant.client.scope))
|
client_scopes = set(scope_to_list(grant.client.scope))
|
||||||
user_scopes = set(scope_to_list(session_scope)) if session_scope else set()
|
user_scopes = set(scope_to_list(session_scope)) if session_scope else set()
|
||||||
|
|
||||||
# Deny authorization if user has no scopes matching the client request
|
# Deny authorization if user lacks scopes requested by client
|
||||||
if not user_scopes & client_scopes:
|
if not client_scopes.issubset(user_scopes):
|
||||||
raise ForbiddenError()
|
raise ForbiddenError('Access denied')
|
||||||
# raise errors.InvalidScopeError(status_code=HTTPStatus.UNAUTHORIZED)
|
|
||||||
|
|
||||||
return server.create_authorization_response(
|
return server.create_authorization_response(
|
||||||
request=router.current_event,
|
request=router.current_event,
|
||||||
|
|||||||
@@ -2,4 +2,5 @@ export const OK = 200
|
|||||||
export const FOUND = 302
|
export const FOUND = 302
|
||||||
export const BAD_REQUEST = 400
|
export const BAD_REQUEST = 400
|
||||||
export const UNAUTHORIZED = 401
|
export const UNAUTHORIZED = 401
|
||||||
|
export const FORBIDDEN = 403
|
||||||
export const INTERNAL_SERVER = 500
|
export const INTERNAL_SERVER = 500
|
||||||
|
|||||||
@@ -6,7 +6,10 @@ import {
|
|||||||
} from '@react-router/dev/routes'
|
} from '@react-router/dev/routes'
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
layout('routes/layout.tsx', [index('routes/index.tsx')]),
|
layout('routes/layout.tsx', [
|
||||||
|
index('routes/index.tsx'),
|
||||||
|
route('/deny', 'routes/deny.tsx')
|
||||||
|
]),
|
||||||
route('/authorize', 'routes/authorize.ts'),
|
route('/authorize', 'routes/authorize.ts'),
|
||||||
route('/token', 'routes/token.ts'),
|
route('/token', 'routes/token.ts'),
|
||||||
route('/revoke', 'routes/revoke.ts')
|
route('/revoke', 'routes/revoke.ts')
|
||||||
|
|||||||
@@ -30,6 +30,12 @@ export async function loader({ request, context }: Route.LoaderArgs) {
|
|||||||
redirect: 'manual'
|
redirect: 'manual'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
console.log('Issuer response', {
|
||||||
|
json: await r.json(),
|
||||||
|
headers: r.headers,
|
||||||
|
status: r.status
|
||||||
|
})
|
||||||
|
|
||||||
if (r.status === httpStatus.FOUND) {
|
if (r.status === httpStatus.FOUND) {
|
||||||
return new Response(await r.text(), {
|
return new Response(await r.text(), {
|
||||||
status: r.status,
|
status: r.status,
|
||||||
@@ -37,11 +43,15 @@ export async function loader({ request, context }: Route.LoaderArgs) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Issuer response', {
|
// Deny authorization if user lacks scopes requested by client
|
||||||
json: await r.json(),
|
if (r.status === httpStatus.FORBIDDEN) {
|
||||||
headers: r.headers,
|
return new Response(null, {
|
||||||
status: r.status
|
status: httpStatus.FOUND,
|
||||||
|
headers: {
|
||||||
|
Location: new URL('/deny', url.origin).toString()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return new Response(null, {
|
return new Response(null, {
|
||||||
status: httpStatus.FOUND,
|
status: httpStatus.FOUND,
|
||||||
|
|||||||
20
id.saladeaula.digital/client/app/routes/deny.tsx
Normal file
20
id.saladeaula.digital/client/app/routes/deny.tsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { LockIcon } from 'lucide-react'
|
||||||
|
import type { Route } from './+types'
|
||||||
|
|
||||||
|
export function meta({}: Route.MetaArgs) {
|
||||||
|
return [{ title: 'Acesso negado' }]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Deny({}: Route.ComponentProps) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="flex flex-col text-center items-center gap-6">
|
||||||
|
<LockIcon className="size-12" />
|
||||||
|
<div className="space-y-1.5">
|
||||||
|
<h1 className="text-xl text-gray-10 font-bold">Acesso negado.</h1>
|
||||||
|
<p>Você não tem permissão.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -8,8 +8,6 @@ export async function action({ request, context }: Route.ActionArgs) {
|
|||||||
body: await request.text()
|
body: await request.text()
|
||||||
})
|
})
|
||||||
|
|
||||||
// console.log(await r.text(), r)
|
|
||||||
|
|
||||||
return new Response(await r.text(), {
|
return new Response(await r.text(), {
|
||||||
status: r.status,
|
status: r.status,
|
||||||
headers: r.headers
|
headers: r.headers
|
||||||
|
|||||||
@@ -53,14 +53,14 @@ def test_authorize(
|
|||||||
assert len(r['items']) == 3
|
assert len(r['items']) == 3
|
||||||
|
|
||||||
|
|
||||||
def test_unauthorized(
|
def test_forbidden(
|
||||||
app,
|
app,
|
||||||
seeds,
|
seeds,
|
||||||
dynamodb_persistence_layer: DynamoDBPersistenceLayer,
|
dynamodb_persistence_layer: DynamoDBPersistenceLayer,
|
||||||
http_api_proxy: HttpApiProxy,
|
http_api_proxy: HttpApiProxy,
|
||||||
lambda_context: LambdaContext,
|
lambda_context: LambdaContext,
|
||||||
):
|
):
|
||||||
session_id = new_session(USER_ID)
|
session_id = new_session('fd5914ec-fd37-458b-b6b9-8aeab38b666b')
|
||||||
|
|
||||||
r = app.lambda_handler(
|
r = app.lambda_handler(
|
||||||
http_api_proxy(
|
http_api_proxy(
|
||||||
@@ -81,7 +81,7 @@ def test_unauthorized(
|
|||||||
lambda_context,
|
lambda_context,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert r['statusCode'] == HTTPStatus.UNAUTHORIZED
|
assert r['statusCode'] == HTTPStatus.FORBIDDEN
|
||||||
|
|
||||||
|
|
||||||
def test_authorize_revoked(
|
def test_authorize_revoked(
|
||||||
|
|||||||
@@ -13,5 +13,9 @@
|
|||||||
// User data
|
// User data
|
||||||
{"id": "357db1c5-7442-4075-98a3-fbe5c938a419", "sk": "0", "name": "Sérgio R Siqueira", "email": "sergio@somosbeta.com.br"}
|
{"id": "357db1c5-7442-4075-98a3-fbe5c938a419", "sk": "0", "name": "Sérgio R Siqueira", "email": "sergio@somosbeta.com.br"}
|
||||||
{"id": "357db1c5-7442-4075-98a3-fbe5c938a419", "sk": "PASSWORD", "hash": "$pbkdf2-sha256$29000$IuTcm7M2BiAEgPB.b.3dGw$d8xVCbx8zxg7MeQBrOvCOgniiilsIHEMHzoH/OXftLQ"}
|
{"id": "357db1c5-7442-4075-98a3-fbe5c938a419", "sk": "PASSWORD", "hash": "$pbkdf2-sha256$29000$IuTcm7M2BiAEgPB.b.3dGw$d8xVCbx8zxg7MeQBrOvCOgniiilsIHEMHzoH/OXftLQ"}
|
||||||
{"id": "357db1c5-7442-4075-98a3-fbe5c938a419", "sk": "SCOPE", "scope": "read:users read:enrollments"}
|
{"id": "357db1c5-7442-4075-98a3-fbe5c938a419", "sk": "SCOPE", "scope": "openid profile email offline_access read:users read:courses"}
|
||||||
{"id": "357db1c5-7442-4075-98a3-fbe5c938a419", "sk": "SESSION#36af142e-9f6d-49d3-bfe9-6a6bd6ab2712", "created_at": "2025-09-17T13:44:34.544491-03:00", "ttl": 1760719474}
|
{"id": "357db1c5-7442-4075-98a3-fbe5c938a419", "sk": "SESSION#36af142e-9f6d-49d3-bfe9-6a6bd6ab2712", "created_at": "2025-09-17T13:44:34.544491-03:00", "ttl": 1760719474}
|
||||||
|
|
||||||
|
{"id": "fd5914ec-fd37-458b-b6b9-8aeab38b666b", "sk": "0", "name": "Johnny Cash", "email": "johnny@johnnycash.com"}
|
||||||
|
{"id": "fd5914ec-fd37-458b-b6b9-8aeab38b666b", "sk": "PASSWORD", "hash": "$pbkdf2-sha256$29000$IuTcm7M2BiAEgPB.b.3dGw$d8xVCbx8zxg7MeQBrOvCOgniiilsIHEMHzoH/OXftLQ"}
|
||||||
|
{"id": "fd5914ec-fd37-458b-b6b9-8aeab38b666b", "sk": "SCOPE", "scope": "openid"}
|
||||||
|
|||||||
Reference in New Issue
Block a user