Skip to content

Commit

Permalink
feat: support extra parameter of client authentication method
Browse files Browse the repository at this point in the history
  • Loading branch information
BigTailWolf committed May 18, 2024
1 parent 7dbedff commit 78c2d51
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 4 deletions.
26 changes: 23 additions & 3 deletions src/auth/oauth2client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ export enum CertificateFormat {
JWK = 'JWK',
}

export enum ClientAuthentication {
ClientSecretPost,
ClientSecretBasic,
None,
}

export interface GetTokenOptions {
code: string;
codeVerifier?: string;
Expand Down Expand Up @@ -475,6 +481,11 @@ export interface OAuth2ClientOptions extends AuthClientOptions {
* The allowed OAuth2 token issuers.
*/
issuers?: string[];
/**
* The client_authentication choice from baisc/post/none
* https://docs.authlib.org/en/latest/client/oauth2.html#client-authentication
*/
client_authentication?: ClientAuthentication;
}

// Re-exporting here for backwards compatibility
Expand All @@ -491,6 +502,7 @@ export class OAuth2Client extends AuthClient {
protected refreshTokenPromises = new Map<string, Promise<GetTokenResponse>>();
readonly endpoints: Readonly<OAuth2ClientEndpoints>;
readonly issuers: string[];
private client_authentication: ClientAuthentication;

// TODO: refactor tests to make this private
_clientId?: string;
Expand Down Expand Up @@ -542,6 +554,7 @@ export class OAuth2Client extends AuthClient {
oauth2IapPublicKeyUrl: 'https://www.gstatic.com/iap/verify/public_key',
...opts.endpoints,
};
this.client_authentication = opts.client_authentication || ClientAuthentication.ClientSecretPost;

Check failure on line 557 in src/auth/oauth2client.ts

View workflow job for this annotation

GitHub Actions / lint

Insert `⏎·····`

this.issuers = opts.issuers || [
'accounts.google.com',
Expand Down Expand Up @@ -660,20 +673,27 @@ export class OAuth2Client extends AuthClient {
options: GetTokenOptions
): Promise<GetTokenResponse> {
const url = this.endpoints.oauth2TokenUrl.toString();
const values = {
let headers: any = {'Content-Type': 'application/x-www-form-urlencoded'};

Check failure on line 676 in src/auth/oauth2client.ts

View workflow job for this annotation

GitHub Actions / lint

'headers' is never reassigned. Use 'const' instead

Check warning on line 676 in src/auth/oauth2client.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
if (this.client_authentication === ClientAuthentication.ClientSecretBasic) {
const basic_auth = 'basic ' + btoa(`${this._clientId}:${this._clientSecret}`);

Check failure on line 678 in src/auth/oauth2client.ts

View workflow job for this annotation

GitHub Actions / lint

Insert `⏎·······`
headers.Authorization = basic_auth;
}
let values: any = {

Check failure on line 681 in src/auth/oauth2client.ts

View workflow job for this annotation

GitHub Actions / lint

'values' is never reassigned. Use 'const' instead

Check warning on line 681 in src/auth/oauth2client.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
code: options.code,
client_id: options.client_id || this._clientId,
client_secret: this._clientSecret,
redirect_uri: options.redirect_uri || this.redirectUri,
grant_type: 'authorization_code',
code_verifier: options.codeVerifier,
};
if (this.client_authentication === ClientAuthentication.ClientSecretPost) {
values.client_secret = this._clientSecret;
}
const res = await this.transporter.request<CredentialRequest>({
...OAuth2Client.RETRY_CONFIG,
method: 'POST',
url,
data: querystring.stringify(values),
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
headers: headers,
});
const tokens = res.data as Credentials;
if (res.data && res.data.expires_in) {
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export {
RefreshOptions,
TokenInfo,
VerifyIdTokenOptions,
ClientAuthentication,
} from './auth/oauth2client';
export {LoginTicket, TokenPayload} from './auth/loginticket';
export {
Expand Down
19 changes: 18 additions & 1 deletion test/test.oauth2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import * as path from 'path';
import * as qs from 'querystring';
import * as sinon from 'sinon';

import {CodeChallengeMethod, Credentials, OAuth2Client} from '../src';
import {CodeChallengeMethod, Credentials, OAuth2Client, ClientAuthentication} from '../src';

Check failure on line 26 in test/test.oauth2.ts

View workflow job for this annotation

GitHub Actions / lint

Replace `CodeChallengeMethod,·Credentials,·OAuth2Client,·ClientAuthentication` with `⏎··CodeChallengeMethod,⏎··Credentials,⏎··OAuth2Client,⏎··ClientAuthentication,⏎`
import {LoginTicket} from '../src/auth/loginticket';

nock.disableNetConnect();
Expand Down Expand Up @@ -1421,6 +1421,23 @@ describe('oauth2', () => {
assert.strictEqual(params.client_id, 'overridden');
});

it('getToken should use basic header auth if provided in options', async () => {
const opts = {
clientId: CLIENT_ID,
clientSecret: CLIENT_SECRET,
redirectUri: REDIRECT_URI,
endpoints: {
oauth2TokenUrl: 'mytokenurl'

Check failure on line 1430 in test/test.oauth2.ts

View workflow job for this annotation

GitHub Actions / lint

Insert `,`
},
client_authentication: ClientAuthentication.ClientSecretBasic,
}

Check failure on line 1433 in test/test.oauth2.ts

View workflow job for this annotation

GitHub Actions / lint

Insert `;`
const oauth2client = new OAuth2Client(opts);
const res = oauth2client.getToken({

Check warning on line 1435 in test/test.oauth2.ts

View workflow job for this annotation

GitHub Actions / lint

'res' is assigned a value but never used
code: 'code here',
client_id: CLIENT_ID,
});
});

it('should return expiry_date', done => {
const now = new Date().getTime();
const scope = nock(baseUrl, {
Expand Down

0 comments on commit 78c2d51

Please sign in to comment.