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
Make it choosable where client id and secret are put and improve expi… #3970
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -74,17 +74,41 @@ export const OAuth2: Secret = { | |
type: 'System.String', | ||
uiHint: 'single-line', | ||
}, | ||
{ | ||
disableWorkflowProviderSelection: false, | ||
isBrowsable: true, | ||
isReadOnly: false, | ||
label: 'Credentials location', | ||
name: 'CredentialsLocation', | ||
order: 4, | ||
supportedSyntaxes: ['Literal'], | ||
type: 'System.String', | ||
uiHint: 'dropdown', | ||
options: { | ||
isFlagsEnum: false, | ||
items: [ | ||
{ | ||
text: 'Authorization header', | ||
value: 'header', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you want to use the standard values, it's |
||
}, | ||
{ | ||
text: 'Form data', | ||
value: 'form', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
] | ||
} | ||
}, | ||
{ | ||
disableWorkflowProviderSelection: false, | ||
isBrowsable: true, | ||
isReadOnly: false, | ||
label: 'Scope', | ||
name: 'Scope', | ||
order: 4, | ||
order: 5, | ||
supportedSyntaxes: ['Literal'], | ||
type: 'System.String', | ||
uiHint: 'single-line', | ||
}, | ||
} | ||
], | ||
type: 'OAuth2', | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,14 +43,17 @@ public async Task<TokenResponse> GetToken(Secret secret, string? authCode, strin | |
{ | ||
var clientId = secret.GetProperty("ClientId"); | ||
var clientSecret = secret.GetProperty("ClientSecret"); | ||
var credentialsLocation = secret.GetProperty("CredentialsLocation") ?? "header"; | ||
var content = new Dictionary<string, string> | ||
{ | ||
{ "grant_type", secret.GetProperty("GrantType") }, | ||
{ "client_id", clientId }, | ||
{ "client_secret", clientSecret }, | ||
{ "offline_access ", "true" } | ||
{ "grant_type", secret.GetProperty("GrantType") } | ||
}; | ||
|
||
if (credentialsLocation == "form") | ||
{ | ||
content.Add("client_id", clientId); | ||
content.Add("client_secret", clientSecret); | ||
} | ||
if (authCode != null) | ||
{ | ||
content.Add("code", authCode); | ||
|
@@ -67,6 +70,10 @@ public async Task<TokenResponse> GetToken(Secret secret, string? authCode, strin | |
{ | ||
var httpClient = _httpClientFactory.CreateClient(nameof(OAuth2TokenService)); | ||
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); | ||
if (credentialsLocation == "header") | ||
{ | ||
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Base64Encode(clientId + ":" + clientSecret)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: while many servers implement it this way, your encoding mechanism is not standard: you must formURL-encode the client identifier and secret before base64-encoding them (i.e do Depending on the OAuth 2.0 services you want to support, you may want to make that configurable. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, you're not really supposed to use the Authorization header option when you don't have a client secret (in this case, you need to send the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added escaping, and since it is standard, and seems to be working with google, I wouldn't make it configurable. That secret modal is getting a bit bloated already, so if someone requires it, they can expand upon this feature. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess so. In this case, you'd probably want to add an Also, |
||
} | ||
|
||
var response = await httpClient.PostAsync(secret.GetProperty("AccessTokenUrl"), new FormUrlEncodedContent(content)); | ||
var json = await response.Content.ReadAsStringAsync(); | ||
|
@@ -92,17 +99,28 @@ public async Task<TokenResponse> GetToken(Secret secret, string? authCode, strin | |
|
||
public async Task<TokenResponse> GetTokenByRefreshToken(Secret secret, string refreshToken) | ||
{ | ||
var clientId = secret.GetProperty("ClientId"); | ||
var clientSecret = secret.GetProperty("ClientSecret"); | ||
var credentialsLocation = secret.GetProperty("CredentialsLocation") ?? "header"; | ||
var content = new Dictionary<string, string> | ||
{ | ||
{ "grant_type", "refresh_token" }, | ||
{ "client_id", secret.GetProperty("ClientId") }, | ||
{ "client_secret", secret.GetProperty("ClientSecret") }, | ||
{ "refresh_token", refreshToken } | ||
}; | ||
|
||
if (credentialsLocation == "form") | ||
{ | ||
content.Add("client_id", clientId); | ||
content.Add("client_secret", clientSecret); | ||
} | ||
|
||
try | ||
{ | ||
var httpClient = _httpClientFactory.CreateClient(nameof(OAuth2TokenService)); | ||
if (credentialsLocation == "header") | ||
{ | ||
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Base64Encode(clientId + ":" + clientSecret)); | ||
} | ||
var response = await httpClient.PostAsync(secret.GetProperty("AccessTokenUrl"), new FormUrlEncodedContent(content)); | ||
var json = await response.Content.ReadAsStringAsync(); | ||
var result = JsonConvert.DeserializeObject<TokenResponse>(json); | ||
|
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.
Note: in case you'd want to use the standard term, it's officially called "token endpoint client authentication method".