-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
76 lines (68 loc) · 3.67 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import axios from "../../services/axios";
import { Logger } from "../../logging";
import type { Dictionary, ProtectorContext } from "../../types";
import { MongoAuthoritiesProvider } from "../AuthoritiesProvider";
import type { IAuthenticationProvider, IAuthenticationProviderProps, IAuthoritiesProvider, IOauth2AuthenticatorProviderProps } from "../types";
import { AxiosError, AxiosResponse } from "axios";
import { ApolloError } from "apollo-server-express";
import { HTTPStatus } from "../../utils";
export class Oauth2AuthenticatorProvider<T extends ProtectorContext> implements IAuthenticationProvider<T> {
private userinfo_endpoint: string = "";
private openidConfiguration: Dictionary<Object> = {};
private logger: Logger = new Logger();
private authoritiesProvider: IAuthoritiesProvider | undefined;
constructor(props: IOauth2AuthenticatorProviderProps = {
enableAuthoritiesProvider: false,
}) {
if (props.userinfo_endpoint)
this.userinfo_endpoint = props.userinfo_endpoint.toString();
else if (props.issuer && props.domain) {
axios.get(`https://${props.domain}/oauth2/${props.issuer}/.well-known/openid-configuration`).then((response) => {
this.openidConfiguration = response.data;
this.userinfo_endpoint = this.openidConfiguration.userinfo_endpoint.toString();
}).catch((err) => {
throw new Error("Error fetching token endpoint from issuer: " + err);
});
} else if (process.env.GRAPHQL_TOOLS_VALIDATE_TOKEN_ENDPOINT)
this.userinfo_endpoint = process.env.GRAPHQL_TOOLS_VALIDATE_TOKEN_ENDPOINT.toString();
else
throw new Error("Missing Oauth2 Mandatory Configuration. Please provide either userinfo_endpoint or issuer and domain.");
if (props.enableAuthoritiesProvider !== undefined && !props.enableAuthoritiesProvider) return;
if (props.authoritiesProvider)
this.authoritiesProvider = props.authoritiesProvider
else if (props.mongoConfig)
this.authoritiesProvider = new MongoAuthoritiesProvider(props.mongoConfig);
else
this.authoritiesProvider = new MongoAuthoritiesProvider();
}
async authenticate(tokenDetails: IAuthenticationProviderProps<T>): Promise<ProtectorContext> {
try {
let response: AxiosResponse<Dictionary<Object>> = await axios.get(this.userinfo_endpoint, {
headers: {
Authorization: tokenDetails.authorization.toString()
}
});
if (!response.data.sub) {
throw new ApolloError(HTTPStatus[401], "401");
}
let authorities = this.authoritiesProvider ? await this.authoritiesProvider.getAuthorities(response.data.sub.toString()) : new Map();
return <ProtectorContext>{
authContext: {
status: "200",
token: tokenDetails.authorization,
methodType: "GET",
authenticated: true,
username: response.data.preferred_username ? response.data.preferred_username.toString() : response.data.sub.toString(),
authorities,
},
}
} catch (error) {
this.logger.error("Error fetching userinfo from token: ", error);
if (error instanceof AxiosError && error.response) {
let status = error.status ? error.status : (error.response.status ? error.response.status : 500);
throw new ApolloError(HTTPStatus[status], String(status));
}
}
throw new ApolloError(HTTPStatus[500], '500');
}
}