Skip to content

Client capabilities

Abhidnya edited this page Sep 3, 2020 · 12 revisions
  • Adding client capabilities to your application object is a way to tell the STS what the client is capable of. So, STS can turn on certain features. For example adding client capability CP1 will mean that client is capable of handling claims challenge from the resource provider(ex: MS Graph). Thus, STS can emit claims in access token that may lead to claims challenge from resource provider(ex: MS Graph).
  • These capabilities are set at the application object using client_capabilities parameter which is a list of client_capability strings.
app = msal.PublicClientApplication(client_id="client_id", authority="your_authority", client_capabilities = ["CP1"])
  • Once these are set at the application level they will be sent to all the calls to STS authorize and token endpoints.
  • When such a capability(CP1) is set on the application object the client application should make sure that a claims challenge from the resource provider(ex: MS Graph) is handled in the application.
  • Claims challenge is a directive in the www-authenticate header that the resource provider(ex: MS Graph) will respond with when an access token is not authorized, and a new access token is required.
  • An example claims challenge from resource provider(ex: MS Graph) should look like this:
HTTP 401; Unauthorized 
www-authenticate=Bearer realm="", 
authorization_uri="https://login.microsoftonline.com/common/oauth2/authorize", 
error="insufficient_claims", 
claims="returned_claims"

It consists of HTTP Status code which must be 401 and www-authenticate header which contains the fields mentioned above. More details about it in this doc. Clients need to extract the claims and then pass it to acquire_token_by_* method.

  • If claims parameter returned from the resource is base64-encoded, it needs to be decoded before calling MSAL. MSAL acquire_token methods accept claims as a json string. This is an example of how claims returned from the resource provider can be handled using authorization code flow.
claims_challenge = "claims returned from resource provider"
# if claims parameter is encoded, decode it and use the decoded claims
# decoded_claims_challenge = str(base64.b64decode(claims), "utf-8")

result = None

# Since you were using your previous AT and then met a claims challenge,
# you should've already be in a context with the current signed-in user.
# Here we assume you somehow already have that account,
# or you could possibly get it like this:
accounts = app.get_accounts()
assert accounts
account = accounts[0]

result = app.acquire_token_silent(scope, account=account, claims_challenge=claims_challenge)
if not result:
    # Auth endpoint call for interactive login (you can use auth url helper)
    auth_url = app.get_authorization_request_url(..., claims_challenge=claims_challenge)
    # Make a request to this auth_url to get back authorization_code
    result = app.acquire_token_by_authorization_code(..., claims_challenge=claims_challenge)
  • This new access token can now be used in the request to resource.
Clone this wiki locally