-
Notifications
You must be signed in to change notification settings - Fork 529
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
feat: Support universe domain #2635
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Almost entirely typo nits; one breaking change that does need fixing.
For ComputeCredential, it looks like we don't detect when we're using a ComputeCredential with an explicitly set universe domain, but that's not the one it's actually running in. I'll need to check the specs again to see if that's okay.
/// After that, this method will always return a completed task. | ||
/// The task's result will never be null. | ||
/// </remarks> | ||
Task<string> GetUniverseDomainAsync(CancellationToken cancellationToken); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And presumably the cancellation token should only ever apply to this call - if this call times out, a later call could still succeed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes! And even viceversa assuming the first cancellation token waits for a shorter time than a second call cancellation token. I'm adding this in docs.
|
||
/// <summary>IAM access token verb.</summary> | ||
internal const string IamAccessTokenVerb = "generateAccessToken"; | ||
|
||
/// <summary>IAM access token endpoint format string. To use it insert the service account email.</summary> | ||
internal static readonly string IamAccessTokenEndpointFormatString = $"{IamServiceAccountEndpointCommonPrefix}{{0}}:{IamAccessTokenVerb}"; | ||
internal static readonly string IamAccessTokenEndpointFormatString = $"{IamServiceAccountEndpointCommonPrefixFormat}{{1}}:{IamAccessTokenVerb}"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can make all of these const, I believe. (Before .NET 6, we couldn't - but IamServiceAccountEndpointCommonPrefixFormat proves that we can use const interpolated strings.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes, true! Done.
using System.Threading.Tasks; | ||
using Xunit; | ||
|
||
namespace Google.Apis.Auth.Tests.OAuth2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
File-scoped namespace?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
||
public IDataStore DataStore => throw new NotImplementedException(); | ||
|
||
public AuthorizationCodeRequestUrl CreateAuthorizationCodeRequest(string redirectUri) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use expression-bodied members for all of these? (I think it's fine for that to mean long lines, probably not even with line-breaks between the methods, for just a block of "stuff we haven't implemented.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
using System.Threading.Tasks; | ||
using Xunit; | ||
|
||
namespace Google.Apis.Auth.Tests.OAuth2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And again... I won't add any more comments like this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, and yes, I'll o through all, thanks!
[Fact] | ||
public async Task WithUniverseDomain() | ||
{ | ||
string principal = "principal"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some comments occasionally would help to make the structure of this test clearer, I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, done!
// i.e. we could calculate the endpoint synchronusly on credential creation. | ||
return TokenServerUrl; | ||
} | ||
string univerDomain = await (this as IGoogleCredential).GetUniverseDomainAsync(cancellationToken: default).ConfigureAwait(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
univerDomain => universeDomain
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
private void ThrowIfCustomTokenUrl() | ||
/// <summary> | ||
/// Returns the token URL to be used by this credential, which may be a custom token URL | ||
/// or the IAM API access tokne endpoint URL which is built using the universe domain and the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tokne => token
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
} | ||
|
||
/// <summary> | ||
/// Get's the id token URL if this credential supports id token emission. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Get's => Gets
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -228,6 +228,10 @@ private static UserCredential CreateUserCredentialFromParameters(JsonCredentialP | |||
{ | |||
throw new InvalidOperationException("JSON data does not represent a valid user credential."); | |||
} | |||
if (credentialParameters.UniverseDomain is not null && credentialParameters.UniverseDomain != GoogleAuthConsts.DefaultUniverseDomain) | |||
{ | |||
throw new InvalidOperationException($"{nameof(UserCredential)} is not supported in other than {GoogleAuthConsts.DefaultUniverseDomain}"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"not supported in other than" => "not supported in universe domains other than"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
||
return await response.Content.ReadAsStringAsync().ConfigureAwait(false); | ||
} | ||
catch (Exception) when (response?.StatusCode == HttpStatusCode.NotFound) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Passing by comment )
what if status code is not 404, but still an error? technically possible.. would it fall into the InvalidOperaition?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that case, and if it's not a timeout (timeout is handled by catching the OperationCanceldException) then the original exception is bubled up. This is also what happens on token fetching, and I'm mimicking that here as per spec.
Does that sound good?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh got it.. I misunderstood the Exception catch the first time. Looks good.
a45fb13
to
84c212d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jskeet , @TimurSadykov I've addressed all your comments.
Changes are in ordered commits that start with Address Review:
, and the last commit is also new.
PTAL, thanks!
|
||
/// <summary>IAM access token verb.</summary> | ||
internal const string IamAccessTokenVerb = "generateAccessToken"; | ||
|
||
/// <summary>IAM access token endpoint format string. To use it insert the service account email.</summary> | ||
internal static readonly string IamAccessTokenEndpointFormatString = $"{IamServiceAccountEndpointCommonPrefix}{{0}}:{IamAccessTokenVerb}"; | ||
internal static readonly string IamAccessTokenEndpointFormatString = $"{IamServiceAccountEndpointCommonPrefixFormat}{{1}}:{IamAccessTokenVerb}"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes, true! Done.
/// After that, this method will always return a completed task. | ||
/// The task's result will never be null. | ||
/// </remarks> | ||
Task<string> GetUniverseDomainAsync(CancellationToken cancellationToken); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes! And even viceversa assuming the first cancellation token waits for a shorter time than a second call cancellation token. I'm adding this in docs.
using System.Threading.Tasks; | ||
using Xunit; | ||
|
||
namespace Google.Apis.Auth.Tests.OAuth2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
||
public IDataStore DataStore => throw new NotImplementedException(); | ||
|
||
public AuthorizationCodeRequestUrl CreateAuthorizationCodeRequest(string redirectUri) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
using System.Threading.Tasks; | ||
using Xunit; | ||
|
||
namespace Google.Apis.Auth.Tests.OAuth2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, and yes, I'll o through all, thanks!
private void ThrowIfCustomTokenUrl() | ||
/// <summary> | ||
/// Returns the token URL to be used by this credential, which may be a custom token URL | ||
/// or the IAM API access tokne endpoint URL which is built using the universe domain and the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
// i.e. we could calculate the endpoint synchronusly on credential creation. | ||
return TokenServerUrl; | ||
} | ||
string univerDomain = await (this as IGoogleCredential).GetUniverseDomainAsync(cancellationToken: default).ConfigureAwait(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
} | ||
|
||
/// <summary> | ||
/// Get's the id token URL if this credential supports id token emission. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
[Fact] | ||
public async Task WithUniverseDomain() | ||
{ | ||
string principal = "principal"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, done!
@@ -228,6 +228,10 @@ private static UserCredential CreateUserCredentialFromParameters(JsonCredentialP | |||
{ | |||
throw new InvalidOperationException("JSON data does not represent a valid user credential."); | |||
} | |||
if (credentialParameters.UniverseDomain is not null && credentialParameters.UniverseDomain != GoogleAuthConsts.DefaultUniverseDomain) | |||
{ | |||
throw new InvalidOperationException($"{nameof(UserCredential)} is not supported in other than {GoogleAuthConsts.DefaultUniverseDomain}"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Yes, thats OK, apparently there will be cases in which one universe accepts credentials from another (related) universe. What we'll need to check is that the service client "intentions" are matched by the credential, i.e. the universe specified for the service client is the same as the one specified for the credential. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
84c212d
to
be38474
Compare
@amanda-tarafa: Is there anything new you'd like me to review here? |
Nope, my last push wash just about squashing the "address review" commits. I'll merge and release later today. |
be38474
to
7c48ae4
Compare
@jskeet for when you get to this, as usual, one commit at a time.