Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable persistent cache for user credentials on Linux and macOS #11134

Closed
5 tasks
chlowell opened this issue Apr 29, 2020 · 11 comments
Closed
5 tasks

Enable persistent cache for user credentials on Linux and macOS #11134

chlowell opened this issue Apr 29, 2020 · 11 comments
Labels
Azure.Identity Client This issue points to a problem in the data-plane of the library.
Milestone

Comments

@chlowell
Copy link
Member

chlowell commented Apr 29, 2020

Azure/azure-sdk-for-java#9188 has design details.

  • adopt msal-extensions~=0.2.0
  • extend cache loading code to include Linux, macOS
  • add keyword argument for opting in to unencrypted fallback (allow_unencrypted_cache)
    • update documentation
      • in particular, Linux requirements
@chlowell
Copy link
Member Author

chlowell commented Jun 9, 2020

This is available now in azure-identity 1.4.0b4. DeviceCodeCredential, InteractiveBrowserCredential, and UsernamePasswordCredential cache in memory by default. The argument enable_persistent_cache opts in to persistent caching. On Linux the cache is encrypted by default, which requires libsecret and PyGObject. You can disable this requirement with the argument allow_unencrypted_cache, which configures the credential to use a plaintext cache when encryption isn't possible.

For example:

from azure.identity import InteractiveBrowserCredential

# opting in to persistent caching
credential = InteractiveBrowserCredential(enable_persistent_cache=True)

# forgoing encryption when it isn't possible
credential = InteractiveBrowserCredential(
    enable_persistent_cache=True, allow_unencrypted_cache=True
)

@chlowell chlowell closed this as completed Jun 9, 2020
@jgentil
Copy link

jgentil commented Oct 20, 2020

Was this rolled back? patch notes indicates that it would be fixed in 1.5.0b1 but as of 1.5.0b2 it has not:

  • Removed application authentication APIs added in 1.4.0 beta versions. These
    will be reintroduced in 1.5.0b1. Passing the keyword arguments below
    generally won't cause a runtime error, but the arguments have no effect.
    • Removed authenticate method from DeviceCodeCredential,
      InteractiveBrowserCredential, and UsernamePasswordCredential
    • Removed allow_unencrypted_cache and enable_persistent_cache keyword
      arguments from CertificateCredential, ClientSecretCredential,
      DeviceCodeCredential, InteractiveBrowserCredential, and
      UsernamePasswordCredential

Is there a plan to reintroduce these?

@chlowell
Copy link
Member Author

I believe #13070 restored that API for 1.5.0b1, and it's present in 1.5.0b2 as well. What's still missing?

@tomerparnasa
Copy link

tomerparnasa commented Dec 14, 2020

Hi, enable_persistent_cache=True does not seem to be working, I tried to use it in 1.5.0b2 and 1.5.0 on a mac device, and every time I am executing my code I get redirected to the web interface to approve my login.
We found only a reference for this when the SDK tries to load a cached token. but nothing regarding writing it in the cache. the cache is located at ~/.IdentityService/msal.cache if I understand it right

@chlowell
Copy link
Member Author

The API we're discussing here isn't in 1.5.0. We removed it from the stable release because we're redesigning it in light of new requirements. In the meantime this API is available in 1.5.0b2, and I expect it to work on a mac. Can you add a code example of what your application is doing? There's a bit more to it than enable_persistent_cache=True. The cache may contain multiple identities, so a newly constructed credential needs to know which to authenticate. The user authentication sample walks through this. Here's the gist:

# if your application hasn't authenticated a user yet, create a credential
# and call authenticate() to get an AuthenticationRecord
credential = InteractiveBrowserCredential(enable_persistent_cache=True)
record = credential.authenticate() 

# serialize the record and store it however you like (it contains no secrets)
serialized_record = record.serialize()

# on subsequent runs, initialize a credential with the record
record = AuthenticationRecord.deserialize(serialized_record)
credential = InteractiveBrowserCredential(enable_persistent_cache=True, authentication_record=record)

@tomerparnasa
Copy link

tomerparnasa commented Dec 17, 2020

Thanks for the answer
I tried your example and it worked. But I have a few questions.
what enable_persistent_cache=True stand for if I need to implement the caching by myself?
overall, I don't understand why the SDK does not handle the token saving (I thought it will write it automatically in ~/.IdentityService/msal.cache), there is any plan to do it?
Also, I would like to know if it is possible to add an expiration date on the token.

@chlowell
Copy link
Member Author

chlowell commented Dec 17, 2020

enable_persistent_cache=True configures the credential to store tokens in a persistent, encrypted cache. The SDK does handle token saving but you won't see data in ~/.IdentityService/msal.cache on macOS because the cache is stored in Keychain.

I would like to know if it is possible to add an expiration date on the token.

All tokens have expiration times set by Azure AD. Do you want to see this time, or to set a different one?

@tomerparnasa
Copy link

Thanks for the answer.
I would like to do both, see the time and to set it if needed.
regarding the persistence, I am not sure I understand, if the SDK handle this, why I need to execute:
record = credential.authenticate():
serialized_record = record.serialize()

and then save it for later use?

@chlowell
Copy link
Member Author

There's no need to set a token's expiration time. It wouldn't be effective (Azure AD determines the value) and credential classes handle caching tokens and replacing expired ones.

You need the record because the cache may contain tokens for an arbitrary number of identities. The record is the key that tells the credential which cached tokens to use.

@tomerparnasa
Copy link

tomerparnasa commented Jan 3, 2021

so why do I need to use enable_persistent_cache=True, If I need to save the record somewhere and then receive it on the next run I would think that the following code should work (without enable_persistent_cache)

# if your application hasn't authenticated a user yet, create a credential
# and call authenticate() to get an AuthenticationRecord
credential = InteractiveBrowserCredential()
record = credential.authenticate() 

# serialize the record and store it however you like (it contains no secrets)
serialized_record = record.serialize()

# on subsequent runs, initialize a credential with the record
record = AuthenticationRecord.deserialize(serialized_record)
credential = InteractiveBrowserCredential(authentication_record=record)

@chlowell
Copy link
Member Author

chlowell commented Jan 4, 2021

I see what you mean: authentication_record=foo typically implies enable_persistent_cache=True, at least in the current beta API. As I wrote above, we're redesigning this API. I think the next revision will remove this implicit redundancy, but I'll keep it in mind as we discuss the design.

@github-actions github-actions bot locked and limited conversation to collaborators Apr 12, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Azure.Identity Client This issue points to a problem in the data-plane of the library.
Projects
None yet
Development

No branches or pull requests

4 participants