Closed philipsd6 closed 11 months ago
Could you progress on this issue? I am also trying to automate retrieval of a token
Your use case calls for a library that supports bearer only authentication. The underlying microsoft package msal is only intended to be used for authentication session management. This is, doing the initial login and then relying on a (cookie) session. Best I can recommend for session-less use case is https://github.com/busykoala/fastapi-opa. If you don't need OPA you can still copy the openid connect part.
python MSAL does not do ANY cryptographic verification, I'm not making this up. See this issue about a reported vulnerability in pyJWT (a python package that can be used to cryptographically verify a JWT token) The response from MSAL authers was they don't use pyJWT for decoding.
Instead MSAL establishes trust from directly receiving the token from the identity provider and trusting the response came from a legitimate server by enforcing https.
I'm making this comment based on the README example:
@app.get("/users/me", response_model=UserInfo, response_model_exclude_none=True, response_model_by_alias=False)
async def read_users_me(current_user: UserInfo = Depends(msal_auth.scheme)) -> UserInfo:
return current_user
SO to answer your initial question, any bearer token that matches you client_id, issuer and is not expired (time wise) will work, but you can easily fake that:
curl --location --request GET 'localhost:5000/users/me' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJqa3lOdnRvbi1tOVludDN0dnFJSDdhV3dKb0xpN0VJLUFnNklSLWxHbWxZIn0.eyJleHAiOjE2NjA0OTkxMjMsImlhdCI6MTY2MDQ5OTA2MywiYXV0aF90aW1lIjoxNjYwNDk5MDYyLCJqdGkiOiIxNTJkYzEwMC02OGI2LTRkZDItODM5YS1kZjFlNjYxNWQzN2IiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvcmVhbG1zL21hc3RlciIsImF1ZCI6InNlY3VyaXR5LWFkbWluLWNvbnNvbGUiLCJzdWIiOiI3Y2U4NzE4ZS0wOTdkLTQ0NGYtYjhmZC1jNmY4MGI1YmVmYzkiLCJ0eXAiOiJJRCIsImF6cCI6InNlY3VyaXR5LWFkbWluLWNvbnNvbGUiLCJub25jZSI6ImYyYmZjNjFiLWExNGYtNDE0My04MDY1LWE1YWY5OGZjZWM2ZiIsInNlc3Npb25fc3RhdGUiOiI4ZDFkNjliYy0xOTVlLTRmOWMtYmE2Yy1mNmFhODRiOTRhMTYiLCJhdF9oYXNoIjoiWXFSaU5KblVKWEhwRFFYU0lOd1JqdyIsImFjciI6IjEiLCJzaWQiOiI4ZDFkNjliYy0xOTVlLTRmOWMtYmE2Yy1mNmFhODRiOTRhMTYiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsInByZWZlcnJlZF91c2VybmFtZSI6ImFkbWluIn0.qE_MbnVxCo17k06zzGOoMWo2WY1NfJt9vefWLh_7umLVbIfXlp260clTs2fifvZHlsiHpHmWt-A8wbNVOberHQ5q3kqcTKAC889sRtSrucdXbvXTrDAt9pxcWO1tS60TQTG8Kl7OAqEC6Wf0_QhQMF1FM3jsFpBtTQdpDtIpowm0BeON19eKaSB-mSo3MejAH1U7D_4f5LP51dU1Nnp3fCGc-dXr6fLXvSmVN5ATEW9jtLi1oBrtvqptr24R0c5XNhdi2aFsEzdtjMEcxKWO53nfCsPu0tzly8ZNSuVl4wZPXO076y1TX-2UVnAtf7K_qp-ojMHic23ozMJN3Lyw-Q'
Session-less or bearer only
Your use case calls for a library that supports bearer only authentication. The underlying microsoft package msal is only intended to be used for authentication session management. This is, doing the initial login and then relying on a (cookie) session. Best I can recommend for session-less use case is https://github.com/busykoala/fastapi-opa. If you don't need OPA you can still copy the openid connect part.
Please don't use this package in a bearer only way it's not secure!
python MSAL does not do ANY cryptographic verification, I'm not making this up. See this issue about a reported vulnerability in pyJWT (a python package that can be used to cryptographically verify a JWT token) The response from MSAL authers was they don't use pyJWT for decoding.
Instead MSAL establishes trust from directly receiving the token from the identity provider and trusting the response came from a legitimate server by enforcing https.
I'm making this comment based on the README example:
@app.get("/users/me", response_model=UserInfo, response_model_exclude_none=True, response_model_by_alias=False) async def read_users_me(current_user: UserInfo = Depends(msal_auth.scheme)) -> UserInfo: return current_user
SO to answer your initial question, any bearer token that matches you client_id, issuer and is not expired (time wise) will work, but you can easily fake that:
curl --location --request GET 'localhost:5000/users/me' \ --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJqa3lOdnRvbi1tOVludDN0dnFJSDdhV3dKb0xpN0VJLUFnNklSLWxHbWxZIn0.eyJleHAiOjE2NjA0OTkxMjMsImlhdCI6MTY2MDQ5OTA2MywiYXV0aF90aW1lIjoxNjYwNDk5MDYyLCJqdGkiOiIxNTJkYzEwMC02OGI2LTRkZDItODM5YS1kZjFlNjYxNWQzN2IiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvcmVhbG1zL21hc3RlciIsImF1ZCI6InNlY3VyaXR5LWFkbWluLWNvbnNvbGUiLCJzdWIiOiI3Y2U4NzE4ZS0wOTdkLTQ0NGYtYjhmZC1jNmY4MGI1YmVmYzkiLCJ0eXAiOiJJRCIsImF6cCI6InNlY3VyaXR5LWFkbWluLWNvbnNvbGUiLCJub25jZSI6ImYyYmZjNjFiLWExNGYtNDE0My04MDY1LWE1YWY5OGZjZWM2ZiIsInNlc3Npb25fc3RhdGUiOiI4ZDFkNjliYy0xOTVlLTRmOWMtYmE2Yy1mNmFhODRiOTRhMTYiLCJhdF9oYXNoIjoiWXFSaU5KblVKWEhwRFFYU0lOd1JqdyIsImFjciI6IjEiLCJzaWQiOiI4ZDFkNjliYy0xOTVlLTRmOWMtYmE2Yy1mNmFhODRiOTRhMTYiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsInByZWZlcnJlZF91c2VybmFtZSI6ImFkbWluIn0.qE_MbnVxCo17k06zzGOoMWo2WY1NfJt9vefWLh_7umLVbIfXlp260clTs2fifvZHlsiHpHmWt-A8wbNVOberHQ5q3kqcTKAC889sRtSrucdXbvXTrDAt9pxcWO1tS60TQTG8Kl7OAqEC6Wf0_QhQMF1FM3jsFpBtTQdpDtIpowm0BeON19eKaSB-mSo3MejAH1U7D_4f5LP51dU1Nnp3fCGc-dXr6fLXvSmVN5ATEW9jtLi1oBrtvqptr24R0c5XNhdi2aFsEzdtjMEcxKWO53nfCsPu0tzly8ZNSuVl4wZPXO076y1TX-2UVnAtf7K_qp-ojMHic23ozMJN3Lyw-Q'
Totally Agree! I wasn't aware this is the initial request, do not mix between the MS authentication to your own website authentication. You could use both, but each should have its own session / key. The very simple example provided is missing the local cache for "session-less" server (but still session full platform).
Hi @philipsd6 , @martin-greentrax , @ejsyx I had just release a new version which will allow you to work that out as long as you are able to keep the same session token in your requests. The new version will fallback into reading the token from the session manager if one is not supplied by the bearer header. I hope this change will assist with your workflow. I'm closing this issue but feel free to open a new one if this one doesn't work out as you requested.
Is your feature request related to a problem? Please describe. The authentication flow from the Swagger Docs UI is clear, but what isn't discussed is how a user could use the API directly from
curl
, without reusing the token retrieved from the Swagger Docs authentication flow.Describe the solution you'd like A session-less/Swagger Doc-less way to use an API I protect with
msal_auth.scheme
. For example:So we need to login:
So I ensure http://localhost:8000/token is added to my app registrations allowed redirect URIs. Then I open the
location
URI in my browser and go through the Azure authentication flow in the portal, just as with the Swagger Docs UI auth flow. It should redirect to my/token
endpoint which will return a token for me to use later:Instead I get
{"detail":"Authentication Error"}
from my local API.Describe alternatives you've considered I've tried to look into service principals, and adding an App Role "Can Invoke my API" but I cannot actually set those up without tenant admin access. I should be able to accomplish my goals without requiring Admin access.
Additional context Going a completely different direction, ideally, we should be able to protect our API with MSAL, but then internally once authenticated, be able to generate granular tokens for use via Curl, etc... i.e. a user might have admin access to the API via roles returned from MSAL, but then once logged into the local API, they should be able to generate a less-privileged token for use in their scripts. I have no idea how one might set that up though.