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

Making all platform-dependent parameters optional #103

Merged
merged 1 commit into from
Dec 8, 2021

Conversation

rayluo
Copy link
Contributor

@rayluo rayluo commented Dec 1, 2021

Changes in this PR

Az CLI uses 2 instances of persistence for different data, stored in different files. @jiasli found it unobvious that he would need to use different service_name and account_name when running on mac. This PR attempts to hide/handle this detail, by automatically generate those 2 parameters based on the (signal) file location.

Future ideas that are not (yet?) in this PR

  1. Historically, before we introduced all those platform-dependent parameters, there was a unified TokenCache interface across all platforms.

  2. Later when we added (more and more) platform-dependent parameters, we attempted to keep a similar cross-platform build_persistence() helper but it did not really hide all those platform-dependent details, it merely becomes a union of all parameters.

    def build_persistence(
        ...,
         entropy='',  # For Windows
         service_name=None, account_name=None,  # For OSX
         schema_name="", attributes=None, fallback_to_plaintext=False,  # For Linux
         **kwargs):  # Extra parameters will be relayed to LibsecretPersistence

    Therefore, @chlowell convinced us to remove that helper, and rightfully so:

    I feel the helper doesn't really help me because it doesn't hide the particulars of persistence. To use it, I must learn which options apply on which platforms, and how; which ones are truly optional. Then I either pass all options at once or call the helper conditionally by platform. I prefer to write the conditional code because it would be easier for future generations to understand. At that point I may as well just import and configure persistence classes directly, that's nicely explicit.

  3. Now, if this PR would be welcomed and merged, the next step would be reconsidering the introduction of a unified helper. This time, it won't need any platform-dependent parameters. Perhaps even a unified Persistence alias:

    # in __init__.py
    if sys.platform.startswith('win'):
        from .persistence import FilePersistenceWithDataProtection as EncryptedPesistence
    elif sys.platform.startswith('darwin'):
        from .persistence import KeyChainPersistnce as EncryptedPesistence
    else:
        from .persistence import LibsecretPersistence as EncryptedPesistence

    This way, the EncryptedPersistence would still be different classes with different signatures on different platforms, but at least their required parameters would be unified so that you could initialize one as EncryptedPersistence('/path/to/my/file.bin'). And that would help resolve https://github.com/AzureAD/microsoft-authentication-extensions-for-python/issues/87.

@chlowell , @jiasli, thoughts?

UPDATE at 12/7/2021: We decided to reject proposal 3, because that alias would end up with different shapes. We postpone proposal 2 to a future release, after we gain some real-world usage with this PR.

@jiasli
Copy link
Contributor

jiasli commented Dec 2, 2021

Personally, I won't really fancy the idea of unifying everything to EncryptedPesistence if their constructor signatures are different. If I need to use platform-specific features, such as service_name, account_name for MacOS, I will need additional if...then... logic, which defeats the purpose of unified interface.

The original build_persistence solution sounds better to me.

@jiasli
Copy link
Contributor

jiasli commented Dec 2, 2021

Related email discussion: Naming for service_name and account_name for MacOS token encryption

@rayluo rayluo force-pushed the unified-persistence-api branch from 52c71e9 to 3e75b23 Compare December 3, 2021 09:08
@rayluo
Copy link
Contributor Author

rayluo commented Dec 3, 2021

Personally, I won't really fancy the idea of unifying everything to EncryptedPesistence if their constructor signatures are different. If I need to use platform-specific features, such as service_name, account_name for MacOS, I will need additional if...then... logic, which defeats the purpose of unified interface.

The original build_persistence solution sounds better to me.

@jiasli , did you mean to say that we can now promote this updated sample's helper def build_persistence(location, fallback_to_plaintext=False) into a formal API?

@rayluo rayluo force-pushed the unified-persistence-api branch from 3e75b23 to c24c190 Compare December 3, 2021 09:25
from .osx import Keychain, KeychainError # pylint: disable=import-outside-toplevel
self._file_persistence = FilePersistence(signal_location) # Favor composition
self._Keychain = Keychain # pylint: disable=invalid-name
self._KeychainError = KeychainError # pylint: disable=invalid-name
self._service_name = service_name
self._account_name = account_name
default_service_name = "Microsoft.Developer.IdentityService" # Stolen from azure-identity
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if MSAL should comply with azure-identity which is actually a downstream library of MSAL.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand that name "Microsoft.Developer.IndentityService" is defined in downstream "azure-identity". Originally, I thought we could use any name so we might as well just backport the name used by "azure-identity".

But you raised a good point. We should NOT knowingly use any downstream specific service name here, because this open-source library msal-extensions could potentially be used by app developers to store any information, and we/they probably do not want to store those data inside a specific downstream component's namespece. I'll send a new commit to use "msal-extensions" as the default service name.

@jiasli
Copy link
Contributor

jiasli commented Dec 6, 2021

@jiasli , did you mean to say that we can now promote this updated sample's helper def build_persistence(location, fallback_to_plaintext=False) into a formal API?

I have no strong opinion. Actually, Azure CLI would prefer not to use this build_persistence, as we tend to use azure-cli as the service_name, which is indeed some customization build_persistence can't provide.

@rayluo rayluo force-pushed the unified-persistence-api branch 2 times, most recently from d01c51b to 8d66d25 Compare December 7, 2021 00:10
@rayluo rayluo force-pushed the unified-persistence-api branch from 8d66d25 to cecb3ac Compare December 7, 2021 19:20
@jiasli
Copy link
Contributor

jiasli commented Dec 8, 2021

Tested with Azure CLI in Azure/azure-cli#20636 and it works perfectly.

@rayluo rayluo force-pushed the unified-persistence-api branch from cecb3ac to 42d482d Compare December 8, 2021 02:37
@rayluo rayluo merged commit 60c2a74 into dev Dec 8, 2021
@rayluo rayluo deleted the unified-persistence-api branch December 8, 2021 02:41
@rayluo rayluo mentioned this pull request Dec 9, 2021
@rayluo rayluo mentioned this pull request Feb 14, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants