Fixed the OIDC token refresh

This commit is contained in:
Brian Leathem
2020-11-23 13:34:44 -08:00
parent a7974a6769
commit 5f1c1c2edf
@@ -33,10 +33,8 @@ import {
OAuthRefreshRequest,
} from '../../lib/oauth';
import {
executeFetchUserProfileStrategy,
executeFrameHandlerStrategy,
executeRedirectStrategy,
executeRefreshTokenStrategy,
PassportDoneCallback,
} from '../../lib/passport';
import { RedirectInfo, AuthProviderFactory, ProfileInfo } from '../types';
@@ -45,20 +43,25 @@ type PrivateInfo = {
refreshToken: string;
};
type OidcImpl = {
strategy: OidcStrategy<UserinfoResponse, Client>;
client: Client;
};
export type OidcAuthProviderOptions = OAuthProviderOptions & {
metadataUrl: string;
tokenSignedResponseAlg?: string;
};
export class OidcAuthProvider implements OAuthHandlers {
readonly _strategy: Promise<OidcStrategy<UserinfoResponse, Client>>;
readonly _implementation: Promise<OidcImpl>;
constructor(options: OidcAuthProviderOptions) {
this._strategy = this.setupStrategy(options);
this._implementation = this.setupStrategy(options);
}
async start(req: OAuthStartRequest): Promise<RedirectInfo> {
const strategy = await this._strategy;
const { strategy } = await this._implementation;
return await executeRedirectStrategy(req, strategy, {
accessType: 'offline',
prompt: 'none',
@@ -70,7 +73,7 @@ export class OidcAuthProvider implements OAuthHandlers {
async handler(
req: express.Request,
): Promise<{ response: OAuthResponse; refreshToken: string }> {
const strategy = await this._strategy;
const { strategy } = await this._implementation;
const { response, privateInfo } = await executeFrameHandlerStrategy<
OAuthResponse,
PrivateInfo
@@ -83,31 +86,19 @@ export class OidcAuthProvider implements OAuthHandlers {
}
async refresh(req: OAuthRefreshRequest): Promise<OAuthResponse> {
const strategy = await this._strategy;
const refreshTokenResponse = await executeRefreshTokenStrategy(
strategy,
req.refreshToken,
req.scope,
);
const {
accessToken,
params,
refreshToken: updatedRefreshToken,
} = refreshTokenResponse;
const profile = await executeFetchUserProfileStrategy(
strategy,
accessToken,
params.id_token,
);
const { client } = await this._implementation;
const tokenset = await client.refresh(req.refreshToken);
if (!tokenset.access_token) {
throw new Error('Refresh failed');
}
const profile = await client.userinfo(tokenset.access_token);
return this.populateIdentity({
providerInfo: {
accessToken,
refreshToken: updatedRefreshToken,
idToken: params.id_token,
expiresInSeconds: params.expires_in,
scope: params.scope,
accessToken: tokenset.access_token,
refreshToken: tokenset.refresh_token,
expiresInSeconds: tokenset.expires_at,
scope: tokenset.scope || '',
},
profile,
});
@@ -115,7 +106,7 @@ export class OidcAuthProvider implements OAuthHandlers {
private async setupStrategy(
options: OidcAuthProviderOptions,
): Promise<OidcStrategy<UserinfoResponse, Client>> {
): Promise<OidcImpl> {
const issuer = await Issuer.discover(options.metadataUrl);
const client = new issuer.Client({
client_id: options.clientId,
@@ -159,7 +150,7 @@ export class OidcAuthProvider implements OAuthHandlers {
},
);
strategy.error = console.error;
return strategy;
return { strategy, client };
}
// Use this function to grab the user profile info from the token