I have created a small demo Fast API with FastAPI-Azure-Auth that authenticates with Microsoft Intra ID. The login works everything is OK. In the app registration for the API I have set up Roles:
And I have assigned them to my user in the APP:
Code for FAST API:
<code>from fastapi import FastAPI,Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi_azure_auth import SingleTenantAzureAuthorizationCodeBearer
import uvicorn
from fastapi import FastAPI, Security
import os
from typing import Dict
from settings import Settings
from pydantic import AnyHttpUrl
from contextlib import asynccontextmanager
from typing import AsyncGenerator
from fastapi_azure_auth.user import User
settings = Settings()
@asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
"""
Load OpenID config on startup.
"""
await azure_scheme.openid_config.load_config()
yield
app = FastAPI(
swagger_ui_oauth2_redirect_url='/oauth2-redirect',
swagger_ui_init_oauth={
'usePkceWithAuthorizationCodeGrant': True,
'clientId': settings.OPENAPI_CLIENT_ID,
'scopes': settings.SCOPE_NAME,
},
)
if settings.BACKEND_CORS_ORIGINS:
app.add_middleware(
CORSMiddleware,
allow_origins=[str(origin) for origin in settings.BACKEND_CORS_ORIGINS],
allow_credentials=True,
allow_methods=['*'],
allow_headers=['*'],
)
azure_scheme = SingleTenantAzureAuthorizationCodeBearer(
app_client_id=settings.APP_CLIENT_ID,
tenant_id=settings.TENANT_ID,
scopes=settings.SCOPES,
)
@app.get("/", dependencies=[Security(azure_scheme)])
async def root():
print("Yo bro")
return {"whoIsTheBest": "DNA Team is"}
@app.get("/test", dependencies=[Security(azure_scheme)])
async def root():
print("Yo test")
return {"whoIsTheBest": "DNA Team is!"}
@app.get("/me", dependencies=[Security(azure_scheme)])
async def me(request: Request) -> Dict[str, bool]:
print("Me")
return request.state.user.roles
if __name__ == '__main__':
uvicorn.run('main:app', reload=True)
</code>
<code>from fastapi import FastAPI,Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi_azure_auth import SingleTenantAzureAuthorizationCodeBearer
import uvicorn
from fastapi import FastAPI, Security
import os
from typing import Dict
from settings import Settings
from pydantic import AnyHttpUrl
from contextlib import asynccontextmanager
from typing import AsyncGenerator
from fastapi_azure_auth.user import User
settings = Settings()
@asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
"""
Load OpenID config on startup.
"""
await azure_scheme.openid_config.load_config()
yield
app = FastAPI(
swagger_ui_oauth2_redirect_url='/oauth2-redirect',
swagger_ui_init_oauth={
'usePkceWithAuthorizationCodeGrant': True,
'clientId': settings.OPENAPI_CLIENT_ID,
'scopes': settings.SCOPE_NAME,
},
)
if settings.BACKEND_CORS_ORIGINS:
app.add_middleware(
CORSMiddleware,
allow_origins=[str(origin) for origin in settings.BACKEND_CORS_ORIGINS],
allow_credentials=True,
allow_methods=['*'],
allow_headers=['*'],
)
azure_scheme = SingleTenantAzureAuthorizationCodeBearer(
app_client_id=settings.APP_CLIENT_ID,
tenant_id=settings.TENANT_ID,
scopes=settings.SCOPES,
)
@app.get("/", dependencies=[Security(azure_scheme)])
async def root():
print("Yo bro")
return {"whoIsTheBest": "DNA Team is"}
@app.get("/test", dependencies=[Security(azure_scheme)])
async def root():
print("Yo test")
return {"whoIsTheBest": "DNA Team is!"}
@app.get("/me", dependencies=[Security(azure_scheme)])
async def me(request: Request) -> Dict[str, bool]:
print("Me")
return request.state.user.roles
if __name__ == '__main__':
uvicorn.run('main:app', reload=True)
</code>
from fastapi import FastAPI,Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi_azure_auth import SingleTenantAzureAuthorizationCodeBearer
import uvicorn
from fastapi import FastAPI, Security
import os
from typing import Dict
from settings import Settings
from pydantic import AnyHttpUrl
from contextlib import asynccontextmanager
from typing import AsyncGenerator
from fastapi_azure_auth.user import User
settings = Settings()
@asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
"""
Load OpenID config on startup.
"""
await azure_scheme.openid_config.load_config()
yield
app = FastAPI(
swagger_ui_oauth2_redirect_url='/oauth2-redirect',
swagger_ui_init_oauth={
'usePkceWithAuthorizationCodeGrant': True,
'clientId': settings.OPENAPI_CLIENT_ID,
'scopes': settings.SCOPE_NAME,
},
)
if settings.BACKEND_CORS_ORIGINS:
app.add_middleware(
CORSMiddleware,
allow_origins=[str(origin) for origin in settings.BACKEND_CORS_ORIGINS],
allow_credentials=True,
allow_methods=['*'],
allow_headers=['*'],
)
azure_scheme = SingleTenantAzureAuthorizationCodeBearer(
app_client_id=settings.APP_CLIENT_ID,
tenant_id=settings.TENANT_ID,
scopes=settings.SCOPES,
)
@app.get("/", dependencies=[Security(azure_scheme)])
async def root():
print("Yo bro")
return {"whoIsTheBest": "DNA Team is"}
@app.get("/test", dependencies=[Security(azure_scheme)])
async def root():
print("Yo test")
return {"whoIsTheBest": "DNA Team is!"}
@app.get("/me", dependencies=[Security(azure_scheme)])
async def me(request: Request) -> Dict[str, bool]:
print("Me")
return request.state.user.roles
if __name__ == '__main__':
uvicorn.run('main:app', reload=True)
However I do not get the roles for my user the dictionary is empty. If I look in the dwt I dont see it there either. Do I need do setup something for roles being included in the response?
<code>{
"typ": "JWT",
"alg": "RS256",
"kid": "xx"
}.{
"aud": "54178xx240bc",
"iss": "https://login.microsoftonline.com/axx/v2.0",
"iat": 1733597326,
"nbf": 1733597326,
"exp": 1733602448,
"aio": "xx",
"azp": "xx",
"azpacr": "0",
"name": "xx - Thomas Segato",
"oid": "xx",
"preferred_username": "xx",
"rh": "xxx",
"scp": "user_impersonation",
"sub": "LxxquqnQ",
"tid": "xxx",
"uti": "xx",
"ver": "2.0"
}.[Signature]
</code>
<code>{
"typ": "JWT",
"alg": "RS256",
"kid": "xx"
}.{
"aud": "54178xx240bc",
"iss": "https://login.microsoftonline.com/axx/v2.0",
"iat": 1733597326,
"nbf": 1733597326,
"exp": 1733602448,
"aio": "xx",
"azp": "xx",
"azpacr": "0",
"name": "xx - Thomas Segato",
"oid": "xx",
"preferred_username": "xx",
"rh": "xxx",
"scp": "user_impersonation",
"sub": "LxxquqnQ",
"tid": "xxx",
"uti": "xx",
"ver": "2.0"
}.[Signature]
</code>
{
"typ": "JWT",
"alg": "RS256",
"kid": "xx"
}.{
"aud": "54178xx240bc",
"iss": "https://login.microsoftonline.com/axx/v2.0",
"iat": 1733597326,
"nbf": 1733597326,
"exp": 1733602448,
"aio": "xx",
"azp": "xx",
"azpacr": "0",
"name": "xx - Thomas Segato",
"oid": "xx",
"preferred_username": "xx",
"rh": "xxx",
"scp": "user_impersonation",
"sub": "LxxquqnQ",
"tid": "xxx",
"uti": "xx",
"ver": "2.0"
}.[Signature]