Skip to content

Access token not being used from the cache with both Files.ReadWrite and User.ReadBasic.All scopes. #450

@cp2004

Description

@cp2004

Describe the bug
I have an implementation accessing MS Graph using MSAL for Python here: OctoPrint OneDrive Backup - provided for reference in case it is needed.

For MS Graph requests I use acquire_token_silent_with_error to get the token & use it in the headers of each request. If I made lots of requests in a row, I noticed that it began erroring and not working anymore. Some investigation followed...

When I called acquire_token_silent_with_error and stepped through it with the debugger, it was showing that it never used the access token from the cache. It was always using the refresh token to get a new token. My scopes I was providing as a list are "User.ReadBasic.All","Files.ReadWrite". In the access token cache, I can see that it is writing:

"AccessToken": {
        "00000000-0000-0000-[REDACTED]-login.microsoftonline.com-accesstoken-1fbab959-f7f1-43c4-a800-5f7f58eb068f-common-files.readwrite openid profile": {
            "credential_type": "AccessToken",
            "secret": "[REDACTED]",
            "home_account_id": "[REDACTED]",
            "environment": "login.microsoftonline.com",
            "client_id": "1fbab959-f7f1-43c4-a800-5f7f58eb068f",
            "target": "Files.ReadWrite openid profile",
            "realm": "common",
            "token_type": "Bearer",
            "cached_at": "1640808717",
            "expires_on": "1640812317",
            "extended_expires_on": "1640812317"
        }
    },

Where the target line is Files.ReadWrite openid profile. In the cache lookup, it is converting this to a set and comparing it to my scopes. They don't match, so it never returns this AT from the cache.

and (target_set <= set(entry.get("target", "").split())

target_set is {"Files.ReadWrite", "User.ReadBasic.all"}, while the comparison is with {"Files.ReadWrite", "openid", "profile"} - and they don't match.

So I removed the User.ReadBasic.all from my scopes list, and I get the same permissions, everything works OK - the stored AT in the cache is now used when requested and I still have access to user data (I think). Not entirely sure what to make of it so I thought I'd document it in case there was something to be done. So my issue is solved, I don't mind if there's nothing to be done here because I misunderstood something.

To Reproduce
Steps to reproduce the behavior:

  1. Using MSAL device flow login, with the code.
  2. Using scopes ["Files.ReadWrite", "User.ReadBasic.all"], and using a persistent cache.
  3. Using acquire_token_silent_with_error, and stepping through with a debugger to figure out what was wrong with the access token not being used from the cache.

Expected behavior
The access token would be correctly selected from the cache.

What you see instead
See above, I think enough is explained.

The MSAL Python version you are using
1.16.0

Additional context
None

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions