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 support for disabling instance discovery for AzureStack scenarios #362

Merged
merged 29 commits into from
Jan 23, 2023

Conversation

sarathys
Copy link
Contributor

Add support for disabling instance discovery for AzureStack and Custom Cloud scenarios

@sarathys sarathys marked this pull request as ready for review November 23, 2022 02:34
Copy link
Collaborator

@chlowell chlowell left a comment

Choose a reason for hiding this comment

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

Do you have tests for this?

apps/internal/oauth/ops/authority/authority.go Outdated Show resolved Hide resolved
apps/public/public.go Outdated Show resolved Hide resolved
apps/confidential/confidential.go Outdated Show resolved Hide resolved
apps/internal/base/base.go Outdated Show resolved Hide resolved
apps/confidential/confidential_test.go Outdated Show resolved Hide resolved
apps/confidential/confidential_test.go Outdated Show resolved Hide resolved
apps/confidential/confidential_test.go Outdated Show resolved Hide resolved
apps/confidential/confidential_test.go Outdated Show resolved Hide resolved
apps/internal/base/base.go Show resolved Hide resolved
apps/internal/base/base.go Outdated Show resolved Hide resolved
apps/confidential/confidential_test.go Outdated Show resolved Hide resolved
apps/confidential/confidential.go Outdated Show resolved Hide resolved
apps/tests/devapps/sample_utils.go Outdated Show resolved Hide resolved
apps/public/public_test.go Outdated Show resolved Hide resolved
apps/public/public_test.go Outdated Show resolved Hide resolved
apps/confidential/confidential_test.go Outdated Show resolved Hide resolved
apps/public/public_test.go Outdated Show resolved Hide resolved
apps/public/public_test.go Outdated Show resolved Hide resolved
apps/confidential/confidential_test.go Outdated Show resolved Hide resolved
apps/public/public.go Outdated Show resolved Hide resolved
apps/internal/base/base.go Outdated Show resolved Hide resolved
t.Fatal(err)
}
}
if ar.AccessToken != accessToken {
Copy link
Member

Choose a reason for hiding this comment

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

I think 2 extra things need to be checked:

  1. HomeAccountId property of Account objects from should be in format "oid.oid" (for AAD it's "oid.tid" but we don't have "tid" in ADFS). This is pretty important, otherwise other MSALs might not be able to read from the cache.
  2. Account object (which is populated from the id token) should have the username set. I believe ADFS will expose this in the "upn" claim and AAD in the "preferred_username" claim. IMO, I would set Username to idToken.preferred_username ?? idToken.upn

Copy link
Member

Choose a reason for hiding this comment

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

Choose a reason for hiding this comment

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

We are setting HomeAccountID like this currently. Do we have to make changes to this? And is this something that should go through in this pr?

// HomeAccountID creates the home account ID.
func (c ClientInfo) HomeAccountID() string {
if c.UID == "" || c.UTID == "" {
return ""
}
return fmt.Sprintf("%s.%s", c.UID, c.UTID)
}

Copy link
Member

@bgavrilMS bgavrilMS Dec 15, 2022

Choose a reason for hiding this comment

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

I think so, otherwise you risk introducing a security issue or a cache miss issue for ADFS only. If home account Id is "", MSAL might not be able to retrieve the correct token from the cache (or it might not be able to retrieve one at all).

if think the logic is:

  • if both are emtpy, homeAccountId is empty (this is probably for client_credentials)
  • if c.UTID == "", then use fmt.Sprintf("%s.%s", c.UID, c.UID)

Copy link
Contributor

Choose a reason for hiding this comment

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

2 extra things need to be checked:

  • HomeAccountId property of Account objects from should be in format "oid.oid" (for AAD it's "oid.tid" but we don't have "tid" in ADFS). This is pretty important, otherwise other MSALs might not be able to read from the cache.

AFAIK, this is an undefined corner case in the original Token Cache Schema. Existing MSALs probably already have inconsistent behaviors here, ranging from "oid"-only to "oid.adfs". The effect is indeed different MSALs would not hit the same account in the cache. Not sure whether it is prevalent in the wild. We did not hear report on this. It is ADFS, anyway.

But if MSAL Go currently returns a completely empty string as HomeAccountID, that sounds too extreme. Better still return something, at least the oid.

  • Account object (which is populated from the id token) should have the username set. I believe ADFS will expose this in the "upn" claim and AAD in the "preferred_username" claim. IMO, I would set Username to idToken.preferred_username ?? idToken.upn

Agreed. MSAL Python did it the same way, too.

And is this something that should go through in this pr?

Not necessarily in this PR, but if it would break Azure Stack scenarios, we may need to fix it sooner or later.

Copy link

@jonnguyen1 jonnguyen1 Dec 15, 2022

Choose a reason for hiding this comment

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

Then there would be cases where we would have UID.UID in AAD, when we are currently getting "" right? Does this pose some type of security issue for AAD? If so, sounds like we should distinguish between ADFS and AAD in the function/make a function for each auth type.

Copy link
Member

Choose a reason for hiding this comment

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

In AAD, the client info has uid and utid claims. In ADFS, it only has uid claim. You don't need to know if authority is ADFS to see that the client_info does not have utid claim.

Just avoid setting HomeAccountId to "" if the uid claim is present. This is a potential security issue, because the cache logic will not be able to differentiate between users.

apps/confidential/confidential_test.go Outdated Show resolved Hide resolved
apps/confidential/confidential_test.go Show resolved Hide resolved
apps/internal/base/base.go Outdated Show resolved Hide resolved
apps/internal/base/internal/storage/partitioned_storage.go Outdated Show resolved Hide resolved
apps/internal/oauth/resolvers.go Show resolved Hide resolved
t.Fatal(err)
}
}
if ar.AccessToken != accessToken {
Copy link
Contributor

Choose a reason for hiding this comment

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

2 extra things need to be checked:

  • HomeAccountId property of Account objects from should be in format "oid.oid" (for AAD it's "oid.tid" but we don't have "tid" in ADFS). This is pretty important, otherwise other MSALs might not be able to read from the cache.

AFAIK, this is an undefined corner case in the original Token Cache Schema. Existing MSALs probably already have inconsistent behaviors here, ranging from "oid"-only to "oid.adfs". The effect is indeed different MSALs would not hit the same account in the cache. Not sure whether it is prevalent in the wild. We did not hear report on this. It is ADFS, anyway.

But if MSAL Go currently returns a completely empty string as HomeAccountID, that sounds too extreme. Better still return something, at least the oid.

  • Account object (which is populated from the id token) should have the username set. I believe ADFS will expose this in the "upn" claim and AAD in the "preferred_username" claim. IMO, I would set Username to idToken.preferred_username ?? idToken.upn

Agreed. MSAL Python did it the same way, too.

And is this something that should go through in this pr?

Not necessarily in this PR, but if it would break Azure Stack scenarios, we may need to fix it sooner or later.

apps/internal/base/internal/storage/partitioned_storage.go Outdated Show resolved Hide resolved
apps/internal/base/base.go Outdated Show resolved Hide resolved
apps/confidential/confidential_test.go Outdated Show resolved Hide resolved
Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com>
apps/confidential/confidential.go Outdated Show resolved Hide resolved
apps/confidential/confidential_test.go Outdated Show resolved Hide resolved
Comment on lines 260 to 262
if account.HomeAccountID != "123-456.123-456" {
t.Fatal("Unexpected Account.HomeAccountId")
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Just a minor nitpick--including the expected and actual values in failure messages helps future debuggers figure out what went wrong:

Suggested change
if account.HomeAccountID != "123-456.123-456" {
t.Fatal("Unexpected Account.HomeAccountId")
}
if actual := account.HomeAccountID; actual != "123-456.123-456" {
t.Fatalf("expected %q, got %q", "123-456.123-456", actual)
}

(tidier if the expected value comes from a variable instead of a literal)

@chlowell chlowell requested a review from rayluo January 19, 2023 00:43
@sonarcloud
Copy link

sonarcloud bot commented Jan 19, 2023

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

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

No Coverage information No Coverage information
No Duplication information No Duplication information

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.

6 participants