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

Add per-request tenant ID option #343

Merged
merged 20 commits into from
Oct 11, 2022
Merged

Add per-request tenant ID option #343

merged 20 commits into from
Oct 11, 2022

Conversation

chlowell
Copy link
Collaborator

@chlowell chlowell commented Aug 17, 2022

This closes #296 by adding a new option, WithTenantID, for public and confidential client token acquisition methods. Tenant resolution follows the logic laid out in #296; see the new tests. Feel free to just look at the tests if you aren't interested in the Go plumbing that makes this new option work.

WithTenantID is straightforward to use in an application but its implementation is complex because it must function alongside options which apply only to particular methods, those methods must accept it without a breaking change to their signatures, and we still want the compiler to prevent users from passing invalid options to a method. Credit goes to @element-of-surprise for the pattern I implemented here.

I exported the new *Option interfaces supporting WithTenantID to enable users to fake Client with their own interfaces (but users can't implement the *Option interfaces). Sadly, this clutters the public API with overlapping names, for example:

type AcquireTokenByAuthCodeOption func(a *AcquireTokenByAuthCodeOptions)
type AcquireByAuthCodeOption interface { ... }
type AcquireTokenByAuthCodeOptions struct { ... }

go.mod Show resolved Hide resolved
@element-of-surprise
Copy link
Contributor

element-of-surprise commented Aug 17, 2022 via email

AcquireSilentOption
shared.CallOption
}{
CallOption: shared.NewCallOption(
Copy link
Member

@bgavrilMS bgavrilMS Aug 31, 2022

Choose a reason for hiding this comment

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

I would add another restriction here, i.e. we should not allow the tenantID to be common or organizations because the intent of this option is to help multi-tenant apps get tokens for specific tenants only. It's ok to go from general to specific, i.e. authority = "l.m.o/common" and tenant = "12345-..", but there aren't any scenarios where you'd want to go from "common" to "common" or from "12345" to "common".

Never mind, this is implemented in authority.go and there are tests for it!

Copy link
Member

@bgavrilMS bgavrilMS Aug 31, 2022

Choose a reason for hiding this comment

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

Also, just FYI / for context, both in client_credentials flow and in OBO flow, calls should not be made over "common" / "organizations".

  • in client_credentials we should outright ban it, because "common" is only supposed to work with user flows
  • in OBO, if you've got a multi-tenant app, the tenant should be incomming_assertion.tid

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

"common" is the default confidential client tenant here, so I opened #348 to track addressing your first point. For OBO, you mean that the application should request a token from the same tenant the user authenticated in i.e., the value of the assertion's tid claim?

.github/workflows/golangci-lint.yml Outdated Show resolved Hide resolved
apps/confidential/confidential.go Show resolved Hide resolved
apps/confidential/confidential.go Show resolved Hide resolved
apps/internal/shared/options.go Outdated Show resolved Hide resolved
apps/public/public.go Outdated Show resolved Hide resolved
Copy link
Contributor

@element-of-surprise element-of-surprise left a comment

Choose a reason for hiding this comment

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

Reviewed from the options part of the code, which lgtm.

Copy link
Contributor

@jhendrixMSFT jhendrixMSFT left a comment

Choose a reason for hiding this comment

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

LGTM although somebody from the MSAL should review the MSAL-specific parts.

@sonarcloud
Copy link

sonarcloud bot commented Oct 10, 2022

SonarCloud Quality Gate failed.    Quality Gate failed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 18 Code Smells

No Coverage information No Coverage information
12.2% 12.2% Duplication

Copy link
Contributor

@rayluo rayluo left a comment

Choose a reason for hiding this comment

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

Thanks for the discussion on the feature. This implementation looks good to me.

@chlowell chlowell merged commit ca8ebc7 into dev Oct 11, 2022
@chlowell chlowell deleted the chlowell/options branch October 11, 2022 22:00
@rayluo rayluo mentioned this pull request Jan 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature Request] Enable changing tenant after client construction
5 participants