56 lines
1.5 KiB
TypeScript
56 lines
1.5 KiB
TypeScript
import jwt from "jsonwebtoken";
|
|
import BaseService from "@Services/BaseService";
|
|
import { Service } from "typedi";
|
|
|
|
export type Tokens = {
|
|
access_token: string;
|
|
expires_in: number;
|
|
id_token: string;
|
|
token_type: string;
|
|
};
|
|
|
|
export type OpenIdConfig = {
|
|
authorization_endpoint: string;
|
|
token_endpoint: string;
|
|
userinfo_endpoint: string;
|
|
claims_supported: string[];
|
|
end_session_endpoint: string;
|
|
grant_types_supported: string[];
|
|
response_types_supported: string[];
|
|
scopes_supported: string[];
|
|
issuer: string;
|
|
jwks_uri: string;
|
|
};
|
|
|
|
@Service()
|
|
export default class OpenIdService extends BaseService {
|
|
protected authorizationServerUrl: string;
|
|
constructor(authorizationServerUrl: string) {
|
|
super();
|
|
this.authorizationServerUrl = authorizationServerUrl;
|
|
}
|
|
|
|
public async getOpenIdConfig(): Promise<OpenIdConfig> {
|
|
const response = await fetch(this.authorizationServerUrl + "/.well-known/openid-configuration");
|
|
return await response.json();
|
|
}
|
|
|
|
public async getSigningKey(kid: string): Promise<string | null> {
|
|
const jwksUri = (await this.getOpenIdConfig()).jwks_uri;
|
|
const response = await fetch(jwksUri);
|
|
const jwks = await response.json();
|
|
const signingKey = jwks.keys.find((key: any) => key.kid === kid);
|
|
if (!signingKey) return null;
|
|
return signingKey;
|
|
}
|
|
|
|
/**
|
|
* @throws Error
|
|
*/
|
|
public async verifyIdToken(idToken: string, kid: string) {
|
|
const signingKey = await this.getSigningKey(kid);
|
|
if (!signingKey) throw new Error("Signing key not found");
|
|
return jwt.verify(idToken, signingKey);
|
|
}
|
|
}
|