Fix resource server error with scope
This commit is contained in:
parent
e9bc6c671a
commit
ad44cf8a67
4 changed files with 20 additions and 15 deletions
|
@ -221,6 +221,7 @@ async def get_user_from_token(
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
user = await db.get_user(user_id)
|
user = await db.get_user(user_id)
|
||||||
|
user.access_token = payload
|
||||||
except UserNotInDB:
|
except UserNotInDB:
|
||||||
logger.info(
|
logger.info(
|
||||||
f"User {user_id} not found in DB, creating it (real apps can behave differently"
|
f"User {user_id} not found in DB, creating it (real apps can behave differently"
|
||||||
|
@ -230,5 +231,6 @@ async def get_user_from_token(
|
||||||
user_info=payload,
|
user_info=payload,
|
||||||
oidc_provider=getattr(authlib_oauth, auth_provider_id),
|
oidc_provider=getattr(authlib_oauth, auth_provider_id),
|
||||||
user_info_from_endpoint={},
|
user_info_from_endpoint={},
|
||||||
|
access_token=payload,
|
||||||
)
|
)
|
||||||
return user
|
return user
|
||||||
|
|
|
@ -26,8 +26,10 @@ class Database:
|
||||||
user_info: dict,
|
user_info: dict,
|
||||||
oidc_provider: StarletteOAuth2App,
|
oidc_provider: StarletteOAuth2App,
|
||||||
user_info_from_endpoint: dict,
|
user_info_from_endpoint: dict,
|
||||||
|
access_token: dict,
|
||||||
) -> User:
|
) -> User:
|
||||||
user = User.from_auth(userinfo=user_info, oidc_provider=oidc_provider)
|
user = User.from_auth(userinfo=user_info, oidc_provider=oidc_provider)
|
||||||
|
user.access_token = access_token
|
||||||
try:
|
try:
|
||||||
raw_roles = user_info_from_endpoint["resource_access"][
|
raw_roles = user_info_from_endpoint["resource_access"][
|
||||||
oidc_provider.client_id
|
oidc_provider.client_id
|
||||||
|
|
|
@ -32,6 +32,7 @@ class User(UserBase):
|
||||||
also the key for the database 'table'""",
|
also the key for the database 'table'""",
|
||||||
)
|
)
|
||||||
userinfo: dict = {}
|
userinfo: dict = {}
|
||||||
|
access_token: dict = {}
|
||||||
oidc_provider: StarletteOAuth2App | None = None
|
oidc_provider: StarletteOAuth2App | None = None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -49,3 +50,9 @@ class User(UserBase):
|
||||||
@cached_property
|
@cached_property
|
||||||
def roles_as_set(self) -> set[str]:
|
def roles_as_set(self) -> set[str]:
|
||||||
return set([role.name for role in self.roles])
|
return set([role.name for role in self.roles])
|
||||||
|
|
||||||
|
def has_scope(self, scope: str) -> bool:
|
||||||
|
"""Check if the scope is present in user info or access token"""
|
||||||
|
info_scopes = self.userinfo.get("scope", "").split(" ")
|
||||||
|
access_token_scopes = self.access_token.get("scope", "").split(" ")
|
||||||
|
return scope in set(info_scopes + access_token_scopes)
|
||||||
|
|
|
@ -22,19 +22,15 @@ async def get_resource(resource_id: str, user: User) -> dict:
|
||||||
# but this has to be refined for production
|
# but this has to be refined for production
|
||||||
required_scope = f"get:{resource_id}"
|
required_scope = f"get:{resource_id}"
|
||||||
# Check if the required scope is in the scopes allowed in userinfo
|
# Check if the required scope is in the scopes allowed in userinfo
|
||||||
if "required_scope" in user.userinfo:
|
if user.has_scope(required_scope):
|
||||||
user_scopes = user.userinfo["required_scope"].split(" ")
|
await process(user, resource_id, resp)
|
||||||
if required_scope in user_scopes:
|
|
||||||
await process(user, required_scope, resp)
|
|
||||||
else:
|
|
||||||
## For the showcase, giving a explanation.
|
|
||||||
## Alternatively, raise HTTP_401_UNAUTHORIZED
|
|
||||||
resp["sorry"] = (
|
|
||||||
f"No scope {required_scope} in the access token "
|
|
||||||
+ "but it is required for accessing this resource."
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
resp["sorry"] = "There is no scope in id token"
|
## For the showcase, giving a explanation.
|
||||||
|
## Alternatively, raise HTTP_401_UNAUTHORIZED
|
||||||
|
resp["sorry"] = (
|
||||||
|
f"No scope {required_scope} in the access token "
|
||||||
|
+ "but it is required for accessing this resource."
|
||||||
|
)
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
|
||||||
|
@ -51,9 +47,7 @@ async def process(user, resource_id, resp):
|
||||||
bs = await client.get("https://corporatebs-generator.sameerkumar.website/")
|
bs = await client.get("https://corporatebs-generator.sameerkumar.website/")
|
||||||
resp["bs"] = bs.json().get("phrase", "Sorry, i am out of BS today.")
|
resp["bs"] = bs.json().get("phrase", "Sorry, i am out of BS today.")
|
||||||
else:
|
else:
|
||||||
resp["sorry"] = (
|
resp["sorry"] = f"I don't known how to give '{resource_id}'."
|
||||||
f"I don't known how to give '{resource_id}' but i know corporate bs."
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# assert user.oidc_provider is not None
|
# assert user.oidc_provider is not None
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue