@kaapi/oauth2-auth-design 0.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +3 -0
  3. package/lib/flows/auth-code/authorization-route.d.ts +53 -0
  4. package/lib/flows/auth-code/authorization-route.js +202 -0
  5. package/lib/flows/auth-code/authorization-route.js.map +1 -0
  6. package/lib/flows/auth-code/open-id.d.ts +53 -0
  7. package/lib/flows/auth-code/open-id.js +199 -0
  8. package/lib/flows/auth-code/open-id.js.map +1 -0
  9. package/lib/flows/auth-code/token-route.d.ts +35 -0
  10. package/lib/flows/auth-code/token-route.js +61 -0
  11. package/lib/flows/auth-code/token-route.js.map +1 -0
  12. package/lib/flows/auth-code.ts/open-id.d.ts +52 -0
  13. package/lib/flows/auth-code.ts/open-id.js +169 -0
  14. package/lib/flows/auth-code.ts/open-id.js.map +1 -0
  15. package/lib/flows/authentication-code.d.ts +53 -0
  16. package/lib/flows/authentication-code.js +380 -0
  17. package/lib/flows/authentication-code.js.map +1 -0
  18. package/lib/flows/client-credentials.d.ts +55 -0
  19. package/lib/flows/client-credentials.js +318 -0
  20. package/lib/flows/client-credentials.js.map +1 -0
  21. package/lib/flows/common.d.ts +139 -0
  22. package/lib/flows/common.js +235 -0
  23. package/lib/flows/common.js.map +1 -0
  24. package/lib/index.d.ts +13 -0
  25. package/lib/index.js +16 -0
  26. package/lib/index.js.map +1 -0
  27. package/lib/utils/cache-set.d.ts +12 -0
  28. package/lib/utils/cache-set.js +35 -0
  29. package/lib/utils/cache-set.js.map +1 -0
  30. package/lib/utils/client-auth-methods.d.ts +77 -0
  31. package/lib/utils/client-auth-methods.js +225 -0
  32. package/lib/utils/client-auth-methods.js.map +1 -0
  33. package/lib/utils/in-memory-cache.d.ts +5 -0
  34. package/lib/utils/in-memory-cache.js +30 -0
  35. package/lib/utils/in-memory-cache.js.map +1 -0
  36. package/lib/utils/in-memory-jwks-store.d.ts +12 -0
  37. package/lib/utils/in-memory-jwks-store.js +46 -0
  38. package/lib/utils/in-memory-jwks-store.js.map +1 -0
  39. package/lib/utils/jwks-generator.d.ts +58 -0
  40. package/lib/utils/jwks-generator.js +141 -0
  41. package/lib/utils/jwks-generator.js.map +1 -0
  42. package/lib/utils/jwks-store.d.ts +13 -0
  43. package/lib/utils/jwks-store.js +3 -0
  44. package/lib/utils/jwks-store.js.map +1 -0
  45. package/lib/utils/token-types.d.ts +46 -0
  46. package/lib/utils/token-types.js +143 -0
  47. package/lib/utils/token-types.js.map +1 -0
  48. package/package.json +44 -0
  49. package/types/overrides.d.ts +14 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-route.js","sourceRoot":"","sources":["../../../src/flows/auth-code/token-route.ts"],"names":[],"mappings":";;;;;AAwCA,MAAa,kBAAkB;IAI3B,MAAM,CAAC,YAAY;QAGf,OAAO,IAAI,yBAAyB,EAAQ,CAAA;IAChD,CAAC;IAKD,IAAI,IAAI;QACJ,OAAO,IAAI,CAAC,KAAK,CAAA;IACrB,CAAC;IAED,IAAI,OAAO;QACP,OAAO,IAAI,CAAC,QAAQ,CAAA;IACxB,CAAC;IAED,YACI,IAAY,EACZ,OAAmC;QAEnC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;IAC5B,CAAC;CACJ;AA5BD,gDA4BC;AAcD,MAAa,yBAEX,SAAQ,kBAAwB;IAI9B;QACI,KAAK,CAAC,eAAe,EAAE,CAAO,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE;YAC3C,IAAI,CAAC,KAAK,CAAC,YAAY,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;gBAC7C,OAAO,CAAC,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,mEAAmE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACrJ,CAAC;YAED,IAAI,CAAC,GAA4E,IAAI,CAAA;YAErF,IAAI,CAAC;gBACD,CAAC,GAAG,MAAM,+BAAA,IAAI,gDAAe,MAAnB,IAAI,EAAgB,KAAK,EAAE,GAAG,CAAC,CAAA;YAC7C,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACX,OAAO,CAAC,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,GAAG,GAAG,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YAC1F,CAAC;YAED,IAAI,CAAC,CAAC;gBAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YAEjE,IAAI,OAAO,IAAI,CAAC;gBAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YAEhD,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAClC,CAAC,CAAA,CAAC,CAAA;QArBN,2DAA4C;QAuBxC,+BAAA,IAAI,4CAAkB,GAAS,EAAE,wDAAC,OAAA,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,CAAA,GAAA,MAAA,CAAA;IACpE,CAAC;IAED,OAAO,CAAC,IAAe;QACnB,IAAI,IAAI;YACJ,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA;QACrB,OAAO,IAAI,CAAA;IACf,CAAC;IAED,QAAQ,CAAC,OAAmC;QACxC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAA;QACvB,OAAO,IAAI,CAAA;IACf,CAAC;IAED,aAAa,CAAC,OAAqC;QAC/C,+BAAA,IAAI,4CAAkB,OAAO,MAAA,CAAA;QAC7B,OAAO,IAAI,CAAA;IACf,CAAC;CACJ;AA7CD,8DA6CC;;AAED,qBAAqB"}
@@ -0,0 +1,52 @@
1
+ import { SecuritySchemeObject } from '@novice1/api-doc-generator/lib/generators/openapi/definitions';
2
+ import { OAuth2Util } from '@novice1/api-doc-generator';
3
+ import { OAuth2AuthorizationCode, OAuth2AuthorizationCodeArg } from '../authentication-code';
4
+ import { KaapiTools, Lifecycle, ReqRef, Request, ReqRefDefaults, ResponseToolkit } from '@kaapi/kaapi';
5
+ import { JWKS } from '../../utils/jwks-store';
6
+ export declare class OpenIDAuthUtil extends OAuth2Util {
7
+ toOpenAPI(): Record<string, SecuritySchemeObject>;
8
+ }
9
+ export interface OpenIDJWKSParams {
10
+ jwks: JWKS;
11
+ }
12
+ export type OpenIDJWKSHandler<Refs extends ReqRef = ReqRefDefaults, R extends Lifecycle.ReturnValue<any> = Lifecycle.ReturnValue<Refs>> = (params: OpenIDJWKSParams, request: Request<Refs>, h: ResponseToolkit<Refs>) => R;
13
+ export interface IOpenIDJWKSRoute<Refs extends ReqRef = ReqRefDefaults> {
14
+ path: string;
15
+ handler?: OpenIDJWKSHandler<Refs>;
16
+ }
17
+ export declare class OpenIDJWKSRoute<Refs extends ReqRef = ReqRefDefaults> implements IOpenIDJWKSRoute<Refs> {
18
+ protected _path: string;
19
+ protected _handler: OpenIDJWKSHandler<Refs> | undefined;
20
+ get path(): string;
21
+ get handler(): OpenIDJWKSHandler<Refs, Lifecycle.ReturnValue<Refs>> | undefined;
22
+ constructor(path: string, handler?: OpenIDJWKSHandler<Refs>);
23
+ }
24
+ export type OpenIDUserInfoHandler<Refs extends ReqRef = ReqRefDefaults, R extends Lifecycle.ReturnValue<any> = Lifecycle.ReturnValue<Refs>> = (request: Request<Refs>, h: ResponseToolkit<Refs>) => R;
25
+ export interface IOpenIDUserInfoRoute<Refs extends ReqRef = ReqRefDefaults> {
26
+ path: string;
27
+ handler?: OpenIDUserInfoHandler<Refs>;
28
+ }
29
+ export declare class OpenIDUserInfoRoute<Refs extends ReqRef = ReqRefDefaults> implements IOpenIDUserInfoRoute<Refs> {
30
+ protected _path: string;
31
+ protected _handler: OpenIDUserInfoHandler<Refs>;
32
+ get path(): string;
33
+ get handler(): OpenIDUserInfoHandler<Refs, Lifecycle.ReturnValue<Refs>>;
34
+ constructor(path: string, handler: OpenIDUserInfoHandler<Refs>);
35
+ }
36
+ export interface OpenIDAuthDesignArg extends OAuth2AuthorizationCodeArg {
37
+ jwksRoute: OpenIDJWKSRoute<any>;
38
+ userInfoRoute: OpenIDUserInfoRoute<any>;
39
+ /**
40
+ * Override the configuration served at /.well-known/openid-configuration
41
+ */
42
+ openidConfiguration?: Record<string, unknown>;
43
+ }
44
+ export declare class OpenIDAuthDesign extends OAuth2AuthorizationCode {
45
+ protected jwksRoute: OpenIDJWKSRoute<any>;
46
+ protected userInfoRoute: OpenIDUserInfoRoute<any>;
47
+ protected openidConfiguration: Record<string, unknown>;
48
+ constructor(params: OpenIDAuthDesignArg);
49
+ getScopes(): Record<string, string>;
50
+ integrateHook(t: KaapiTools): void;
51
+ docs(): OAuth2Util;
52
+ }
@@ -0,0 +1,169 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OpenIDAuthDesign = exports.OpenIDUserInfoRoute = exports.OpenIDJWKSRoute = exports.OpenIDAuthUtil = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const api_doc_generator_1 = require("@novice1/api-doc-generator");
6
+ const authentication_code_1 = require("../authentication-code");
7
+ //#region OpenIDAuthUtil
8
+ class OpenIDAuthUtil extends api_doc_generator_1.OAuth2Util {
9
+ toOpenAPI() {
10
+ const host = this.getHost();
11
+ return {
12
+ [this.securitySchemeName]: {
13
+ type: 'openIdConnect',
14
+ openIdConnectUrl: `${host || ''}/.well-known/openid-configuration`
15
+ }
16
+ };
17
+ }
18
+ }
19
+ exports.OpenIDAuthUtil = OpenIDAuthUtil;
20
+ class OpenIDJWKSRoute {
21
+ get path() {
22
+ return this._path;
23
+ }
24
+ get handler() {
25
+ return this._handler;
26
+ }
27
+ constructor(path, handler) {
28
+ this._path = path;
29
+ this._handler = handler;
30
+ }
31
+ }
32
+ exports.OpenIDJWKSRoute = OpenIDJWKSRoute;
33
+ class OpenIDUserInfoRoute {
34
+ get path() {
35
+ return this._path;
36
+ }
37
+ get handler() {
38
+ return this._handler;
39
+ }
40
+ constructor(path, handler) {
41
+ this._path = path;
42
+ this._handler = handler;
43
+ }
44
+ }
45
+ exports.OpenIDUserInfoRoute = OpenIDUserInfoRoute;
46
+ class OpenIDAuthDesign extends authentication_code_1.OAuth2AuthorizationCode {
47
+ constructor(params) {
48
+ const { strategyName, openidConfiguration, jwksRoute, userInfoRoute } = params, props = tslib_1.__rest(params, ["strategyName", "openidConfiguration", "jwksRoute", "userInfoRoute"]);
49
+ super(props);
50
+ this.openidConfiguration = {};
51
+ this.pkce = true;
52
+ this.strategyName = strategyName || 'open-id-auth-design';
53
+ this.jwksRoute = jwksRoute;
54
+ this.userInfoRoute = userInfoRoute;
55
+ if (openidConfiguration)
56
+ this.openidConfiguration = openidConfiguration;
57
+ }
58
+ getScopes() {
59
+ let scopes = {
60
+ openid: 'enable OpenID Connect'
61
+ };
62
+ if (this.scopes) {
63
+ if ('openid' in this.scopes) {
64
+ scopes = this.scopes;
65
+ }
66
+ else {
67
+ scopes = Object.assign(Object.assign({}, this.scopes), scopes);
68
+ }
69
+ }
70
+ return scopes;
71
+ }
72
+ integrateHook(t) {
73
+ var _a;
74
+ super.integrateHook(t);
75
+ const docs = this.docs();
76
+ const challengeAlgo = docs.getChallengeAlgorithm();
77
+ const host = ((_a = t.postman) === null || _a === void 0 ? void 0 : _a.getHost()[0]) || '';
78
+ t.route({
79
+ path: '/.well-known/openid-configuration',
80
+ method: 'GET',
81
+ options: {
82
+ plugins: {
83
+ kaapi: {
84
+ docs: false
85
+ }
86
+ }
87
+ },
88
+ handler: () => {
89
+ return Object.assign({ issuer: host, authorization_endpoint: `${host}${this.authorizationRoute.path}`, token_endpoint: `${host}${this.tokenRoute.path}`, userinfo_endpoint: `${host}${this.userInfoRoute.path}`, jwks_uri: `${host}${this.jwksRoute.path}`, claims_supported: [
90
+ 'aud',
91
+ 'exp',
92
+ 'iat',
93
+ 'iss',
94
+ 'sub'
95
+ ], grant_types_supported: [
96
+ 'authorization_code'
97
+ ], response_types_supported: [
98
+ 'code',
99
+ 'token',
100
+ 'code token',
101
+ 'code token id_token'
102
+ ], scopes_supported: Object.keys(docs.getScopes()), subject_types_supported: [
103
+ 'public'
104
+ ], id_token_signing_alg_values_supported: [
105
+ 'RS256'
106
+ ], code_challenge_methods_supported: challengeAlgo ? [
107
+ challengeAlgo
108
+ ] : [], token_endpoint_auth_methods_supported: [
109
+ 'client_secret_post'
110
+ ] }, this.openidConfiguration);
111
+ }
112
+ });
113
+ t.route({
114
+ path: this.jwksRoute.path,
115
+ method: 'GET',
116
+ options: {
117
+ plugins: {
118
+ kaapi: {
119
+ docs: false
120
+ }
121
+ }
122
+ },
123
+ handler: (req, h) => tslib_1.__awaiter(this, void 0, void 0, function* () {
124
+ const jwks = yield this.jwksGenerator.get();
125
+ if (this.jwksRoute.handler) {
126
+ return this.jwksRoute.handler({
127
+ jwks
128
+ }, req, h);
129
+ }
130
+ return jwks;
131
+ })
132
+ });
133
+ t.route({
134
+ path: this.userInfoRoute.path,
135
+ method: 'GET',
136
+ options: {
137
+ auth: {
138
+ strategy: this.strategyName,
139
+ mode: 'required'
140
+ },
141
+ plugins: {
142
+ kaapi: {
143
+ docs: false
144
+ }
145
+ }
146
+ },
147
+ handler: this.userInfoRoute.handler.bind(this.userInfoRoute)
148
+ });
149
+ }
150
+ docs() {
151
+ var _a;
152
+ const docs = new OpenIDAuthUtil(this.strategyName)
153
+ .setGrantType(this.isWithPkce() ? api_doc_generator_1.GrantType.authorizationCodeWithPkce : api_doc_generator_1.GrantType.authorizationCode)
154
+ .setScopes(this.getScopes())
155
+ .setAuthUrl(this.authorizationRoute.path)
156
+ .setAccessTokenUrl(this.tokenRoute.path || '')
157
+ .setChallengeAlgorithm(api_doc_generator_1.ChallengeAlgorithm.S256);
158
+ if ((_a = this.refreshTokenRoute) === null || _a === void 0 ? void 0 : _a.path) {
159
+ docs.setRefreshUrl(this.refreshTokenRoute.path);
160
+ }
161
+ if (this.description) {
162
+ docs.setDescription(this.description);
163
+ }
164
+ return docs;
165
+ }
166
+ }
167
+ exports.OpenIDAuthDesign = OpenIDAuthDesign;
168
+ //#endregion OpenIDAuthDesign
169
+ //# sourceMappingURL=open-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-id.js","sourceRoot":"","sources":["../../../src/flows/auth-code.ts/open-id.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import { KaapiTools } from '@kaapi/kaapi';
2
+ import { OAuth2Util } from '@novice1/api-doc-generator';
3
+ import { IOAuth2RefreshTokenRoute, OAuth2WithJWKSAuthDesign, OAuth2AuthOptions } from './common';
4
+ import { JWKSStore } from '../utils/jwks-store';
5
+ import { IOAuth2ACAuthorizationRoute } from './auth-code/authorization-route';
6
+ import { IOAuth2ACTokenRoute } from './auth-code/token-route';
7
+ export interface OAuth2AuthorizationCodeArg {
8
+ authorizationRoute: IOAuth2ACAuthorizationRoute<any, any>;
9
+ tokenRoute: IOAuth2ACTokenRoute<any>;
10
+ refreshTokenRoute?: IOAuth2RefreshTokenRoute<any>;
11
+ options?: OAuth2AuthOptions;
12
+ strategyName?: string;
13
+ jwksStore?: JWKSStore;
14
+ }
15
+ export declare class OAuth2AuthorizationCode extends OAuth2WithJWKSAuthDesign {
16
+ protected strategyName: string;
17
+ protected description?: string;
18
+ protected scopes?: Record<string, string>;
19
+ protected options: OAuth2AuthOptions;
20
+ protected pkce: boolean;
21
+ protected clientAuthenticationMethods: {
22
+ header: boolean;
23
+ body: boolean;
24
+ };
25
+ protected authorizationRoute: IOAuth2ACAuthorizationRoute<any, any>;
26
+ protected tokenRoute: IOAuth2ACTokenRoute<any>;
27
+ protected refreshTokenRoute?: IOAuth2RefreshTokenRoute<any>;
28
+ constructor({ authorizationRoute, tokenRoute, refreshTokenRoute, options, strategyName, jwksStore }: OAuth2AuthorizationCodeArg);
29
+ withPkce(): this;
30
+ withoutPkce(): this;
31
+ isWithPkce(): boolean;
32
+ noneAuthenticationMethod(): this;
33
+ setDescription(description: string): this;
34
+ /**
35
+ *
36
+ * @param scopes The scopes of the access request.
37
+ * A map between the scope name and a short description for it. The map MAY be empty.
38
+ * @returns
39
+ */
40
+ setScopes(scopes: Record<string, string>): this;
41
+ getScopes(): Record<string, string> | undefined;
42
+ getStrategyName(): string;
43
+ getDescription(): string | undefined;
44
+ /**
45
+ * Returns the schema used for the documentation
46
+ */
47
+ docs(): OAuth2Util;
48
+ /**
49
+ * Where authentication schemes and strategies are registered.
50
+ */
51
+ integrateStrategy(t: KaapiTools): void;
52
+ integrateHook(t: KaapiTools): void;
53
+ }
@@ -0,0 +1,380 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OAuth2AuthorizationCode = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const api_doc_generator_1 = require("@novice1/api-doc-generator");
6
+ const boom_1 = tslib_1.__importDefault(require("@hapi/boom"));
7
+ const hoek_1 = tslib_1.__importDefault(require("@hapi/hoek"));
8
+ const common_1 = require("./common");
9
+ const jwks_generator_1 = require("../utils/jwks-generator");
10
+ class OAuth2AuthorizationCode extends common_1.OAuth2WithJWKSAuthDesign {
11
+ constructor({ authorizationRoute, tokenRoute, refreshTokenRoute, options, strategyName, jwksStore }) {
12
+ super(jwksStore);
13
+ this.pkce = false;
14
+ this.clientAuthenticationMethods = {
15
+ header: false,
16
+ body: false
17
+ };
18
+ this.authorizationRoute = authorizationRoute;
19
+ this.tokenRoute = tokenRoute;
20
+ this.refreshTokenRoute = refreshTokenRoute;
21
+ this.strategyName = strategyName || 'oauth2-authorization-code';
22
+ this.options = options ? Object.assign({}, options) : {};
23
+ }
24
+ withPkce() {
25
+ this.pkce = true;
26
+ return super.noneAuthenticationMethod();
27
+ }
28
+ withoutPkce() {
29
+ this.pkce = false;
30
+ this._clientAuthMethods.none = undefined;
31
+ return this;
32
+ }
33
+ isWithPkce() {
34
+ return this.pkce;
35
+ }
36
+ noneAuthenticationMethod() {
37
+ return this.withPkce();
38
+ }
39
+ setDescription(description) {
40
+ this.description = description;
41
+ return this;
42
+ }
43
+ /**
44
+ *
45
+ * @param scopes The scopes of the access request.
46
+ * A map between the scope name and a short description for it. The map MAY be empty.
47
+ * @returns
48
+ */
49
+ setScopes(scopes) {
50
+ this.scopes = scopes;
51
+ return this;
52
+ }
53
+ getScopes() {
54
+ return this.scopes;
55
+ }
56
+ getStrategyName() {
57
+ return this.strategyName;
58
+ }
59
+ getDescription() {
60
+ return this.description;
61
+ }
62
+ /**
63
+ * Returns the schema used for the documentation
64
+ */
65
+ docs() {
66
+ var _a;
67
+ const docs = new api_doc_generator_1.OAuth2Util(this.strategyName)
68
+ .setGrantType(this.isWithPkce() ? api_doc_generator_1.GrantType.authorizationCodeWithPkce : api_doc_generator_1.GrantType.authorizationCode)
69
+ .setScopes(this.getScopes() || {})
70
+ .setAuthUrl(this.authorizationRoute.path)
71
+ .setAccessTokenUrl(this.tokenRoute.path || '');
72
+ const supported = this.getTokenEndpointAuthMethods();
73
+ if (supported.includes('client_secret_post')) {
74
+ docs.setChallengeAlgorithm(api_doc_generator_1.ClientAuthentication.body);
75
+ }
76
+ else if (supported.includes('client_secret_basic')) {
77
+ docs.setChallengeAlgorithm(api_doc_generator_1.ClientAuthentication.header);
78
+ }
79
+ if ((_a = this.refreshTokenRoute) === null || _a === void 0 ? void 0 : _a.path) {
80
+ docs.setRefreshUrl(this.refreshTokenRoute.path);
81
+ }
82
+ if (this.description) {
83
+ docs.setDescription(this.description);
84
+ }
85
+ return docs;
86
+ }
87
+ /**
88
+ * Where authentication schemes and strategies are registered.
89
+ */
90
+ integrateStrategy(t) {
91
+ const tokenTypePrefix = this.tokenType;
92
+ const tokenTypeInstance = this._tokenType;
93
+ t.scheme(this.strategyName, (_server, options) => {
94
+ return {
95
+ authenticate(request, h) {
96
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
97
+ var _a;
98
+ const settings = hoek_1.default.applyToDefaults({}, options || {});
99
+ const authorization = request.raw.req.headers.authorization;
100
+ const authSplit = authorization ? authorization.split(/\s+/) : ['', ''];
101
+ const tokenType = authSplit[0];
102
+ let token = authSplit[1];
103
+ if (tokenType.toLowerCase() !== tokenTypePrefix.toLowerCase()) {
104
+ token = '';
105
+ return boom_1.default.unauthorized(null, tokenTypePrefix);
106
+ }
107
+ if (!(yield tokenTypeInstance.isValid(request, token)).isValid) {
108
+ return boom_1.default.unauthorized(null, tokenTypePrefix);
109
+ }
110
+ if (settings.validate) {
111
+ try {
112
+ const result = yield ((_a = settings.validate) === null || _a === void 0 ? void 0 : _a.call(settings, request, token, h));
113
+ if (result && 'isAuth' in result) {
114
+ return result;
115
+ }
116
+ if (result && 'isBoom' in result) {
117
+ return result;
118
+ }
119
+ if (result) {
120
+ const { isValid, credentials, artifacts, message } = result;
121
+ if (isValid && credentials) {
122
+ return h.authenticated({ credentials, artifacts });
123
+ }
124
+ if (message) {
125
+ return h.unauthenticated(boom_1.default.unauthorized(message, tokenTypePrefix), {
126
+ credentials: credentials || {},
127
+ artifacts
128
+ });
129
+ }
130
+ }
131
+ }
132
+ catch (err) {
133
+ return boom_1.default.internal(err instanceof Error ? err : `${err}`);
134
+ }
135
+ }
136
+ return boom_1.default.unauthorized(null, tokenTypePrefix);
137
+ });
138
+ },
139
+ };
140
+ });
141
+ t.strategy(this.strategyName, this.strategyName, this.options);
142
+ }
143
+ integrateHook(t) {
144
+ var _a;
145
+ const hasOpenIDScope = () => { var _a; return typeof ((_a = this.getScopes()) === null || _a === void 0 ? void 0 : _a['openid']) != 'undefined'; };
146
+ const tokenTypeInstance = this._tokenType;
147
+ const supported = this.getTokenEndpointAuthMethods();
148
+ const authMethodsInstances = this.clientAuthMethods;
149
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
150
+ const routesOptions = {
151
+ plugins: {
152
+ kaapi: {
153
+ docs: false
154
+ }
155
+ }
156
+ };
157
+ t
158
+ .route({
159
+ options: routesOptions,
160
+ path: this.authorizationRoute.path,
161
+ method: ['GET', 'POST'],
162
+ handler: (req, h) => tslib_1.__awaiter(this, void 0, void 0, function* () {
163
+ // validating query
164
+ if (req.query.client_id && typeof req.query.client_id === 'string' &&
165
+ req.query.response_type === 'code' &&
166
+ req.query.redirect_uri && typeof req.query.redirect_uri === 'string') {
167
+ const params = {
168
+ clientId: req.query.client_id,
169
+ redirectUri: req.query.redirect_uri,
170
+ responseType: req.query.response_type
171
+ };
172
+ if (req.query.scope && typeof req.query.scope === 'string') {
173
+ params.scope = req.query.scope;
174
+ }
175
+ if (req.query.state && typeof req.query.state === 'string') {
176
+ params.state = req.query.state;
177
+ }
178
+ if (req.query.code_challenge && typeof req.query.code_challenge === 'string') {
179
+ params.codeChallenge = req.query.code_challenge;
180
+ }
181
+ if (req.query.nonce && typeof req.query.nonce === 'string') {
182
+ params.nonce = req.query.nonce;
183
+ }
184
+ if (req.method.toLowerCase() === 'get') {
185
+ return this.authorizationRoute.handler(params, req, h);
186
+ }
187
+ else {
188
+ return this.authorizationRoute.postHandler(params, req, h);
189
+ }
190
+ }
191
+ else {
192
+ let errorDescription = '';
193
+ if (!(req.query.client_id && typeof req.query.client_id === 'string')) {
194
+ errorDescription = 'Request was missing the \'client_id\' parameter.';
195
+ }
196
+ else if (!(req.query.response_type === 'code')) {
197
+ errorDescription = `Request does not support the 'response_type' '${req.query.response_type}'.`;
198
+ }
199
+ else if (!(req.query.redirect_uri && typeof req.query.redirect_uri === 'string')) {
200
+ errorDescription = 'Request was missing the \'redirect_uri\' parameter.';
201
+ }
202
+ return h.response({ error: 'invalid_request', error_description: errorDescription }).code(400);
203
+ }
204
+ })
205
+ })
206
+ .route({
207
+ options: routesOptions,
208
+ path: this.tokenRoute.path,
209
+ method: 'POST',
210
+ handler: (req, h) => tslib_1.__awaiter(this, void 0, void 0, function* () {
211
+ var _a, _b;
212
+ // Grant validation
213
+ const supportedGrants = ['authorization_code'];
214
+ if (this.tokenRoute.path == ((_a = this.refreshTokenRoute) === null || _a === void 0 ? void 0 : _a.path)) {
215
+ supportedGrants.push('refresh_token');
216
+ }
217
+ if (!(typeof req.payload.grant_type === 'string' && supportedGrants.includes(req.payload.grant_type))) {
218
+ return h.response({ error: 'unsupported_grant_type', error_description: `Request does not support the 'grant_type' '${req.payload.grant_type}'.` }).code(400);
219
+ }
220
+ // Client authentication is present?
221
+ const { clientId, clientSecret, error, errorDescription } = yield this._extractClientParams(req, authMethodsInstances, supported);
222
+ if (error) {
223
+ return h.response({ error: error, error_description: errorDescription || undefined }).code(400);
224
+ }
225
+ if (!clientId) {
226
+ return h
227
+ .response({
228
+ error: 'invalid_request',
229
+ error_description: `Supported token endpoint authentication methods: ${supported.join(', ')}`
230
+ }).code(400);
231
+ }
232
+ if (clientId &&
233
+ req.payload.code && typeof req.payload.code === 'string' &&
234
+ req.payload.grant_type === 'authorization_code') {
235
+ const params = {
236
+ clientId,
237
+ grantType: req.payload.grant_type,
238
+ code: req.payload.code,
239
+ ttl: this.jwksGenerator.ttl,
240
+ createIDToken: hasOpenIDScope() ? ((payload) => tslib_1.__awaiter(this, void 0, void 0, function* () {
241
+ var _a;
242
+ return yield (0, jwks_generator_1.createIDToken)(this.jwksGenerator, Object.assign({ aud: clientId, iss: ((_a = t.postman) === null || _a === void 0 ? void 0 : _a.getHost()[0]) || '' }, payload));
243
+ })) : undefined
244
+ };
245
+ if (clientSecret) {
246
+ params.clientSecret = clientSecret;
247
+ }
248
+ if (req.payload.code_verifier && typeof req.payload.code_verifier === 'string') {
249
+ params.codeVerifier = req.payload.code_verifier;
250
+ }
251
+ if (req.payload.redirect_uri && typeof req.payload.redirect_uri === 'string') {
252
+ params.redirectUri = req.payload.redirect_uri;
253
+ }
254
+ const ttR = tokenTypeInstance.isValidTokenRequest ? (yield tokenTypeInstance.isValidTokenRequest(req)) : { isValid: true };
255
+ if (!ttR.isValid) {
256
+ return h.response({ error: 'invalid_request', error_description: ttR.message || '' }).code(400);
257
+ }
258
+ return this.tokenRoute.handler(params, req, h);
259
+ }
260
+ else if (this.tokenRoute.path == ((_b = this.refreshTokenRoute) === null || _b === void 0 ? void 0 : _b.path) &&
261
+ req.payload.grant_type === 'refresh_token') {
262
+ const hasRefreshToken = req.payload.refresh_token && typeof req.payload.refresh_token === 'string';
263
+ if (clientId &&
264
+ hasRefreshToken) {
265
+ const params = {
266
+ clientId,
267
+ grantType: req.payload.grant_type,
268
+ refreshToken: `${req.payload.refresh_token}`,
269
+ ttl: this.jwksGenerator.ttl,
270
+ createIDToken: hasOpenIDScope() ? ((payload) => tslib_1.__awaiter(this, void 0, void 0, function* () {
271
+ var _a;
272
+ return yield (0, jwks_generator_1.createIDToken)(this.jwksGenerator, Object.assign({ aud: clientId, iss: ((_a = t.postman) === null || _a === void 0 ? void 0 : _a.getHost()[0]) || '' }, payload));
273
+ })) : undefined
274
+ };
275
+ if (clientSecret) {
276
+ params.clientSecret = clientSecret;
277
+ }
278
+ if (req.payload.scope && typeof req.payload.scope === 'string') {
279
+ params.scope = req.payload.scope;
280
+ }
281
+ return this.refreshTokenRoute.handler(params, req, h);
282
+ }
283
+ else {
284
+ let error = 'unauthorized_client';
285
+ let errorDescription = '';
286
+ if (!clientId) {
287
+ error = 'invalid_request';
288
+ errorDescription = 'Request was missing the \'client_id\' parameter.';
289
+ }
290
+ else if (!(req.payload.refresh_token && typeof req.payload.refresh_token === 'string')) {
291
+ error = 'invalid_request';
292
+ errorDescription = 'Request was missing the \'refresh_token\' parameter.';
293
+ }
294
+ return h.response({ error, error_description: errorDescription }).code(400);
295
+ }
296
+ }
297
+ else {
298
+ let error = 'unauthorized_client';
299
+ let errorDescription = '';
300
+ if (!clientId) {
301
+ error = 'invalid_request';
302
+ errorDescription = 'Request was missing the \'client_id\' parameter.';
303
+ }
304
+ else if (!(req.payload.code && typeof req.payload.code === 'string')) {
305
+ error = 'invalid_request';
306
+ errorDescription = 'Request was missing the \'code\' parameter.';
307
+ }
308
+ return h.response({ error, error_description: errorDescription }).code(400);
309
+ }
310
+ })
311
+ });
312
+ // refreshToken
313
+ if (((_a = this.refreshTokenRoute) === null || _a === void 0 ? void 0 : _a.path) && this.refreshTokenRoute.path != this.tokenRoute.path) {
314
+ t.route({
315
+ options: routesOptions,
316
+ path: this.refreshTokenRoute.path,
317
+ method: 'POST',
318
+ handler: (req, h) => tslib_1.__awaiter(this, void 0, void 0, function* () {
319
+ var _a;
320
+ // Grant validation
321
+ const supportedGrants = ['refresh_token'];
322
+ if (!(typeof req.payload.grant_type === 'string' && supportedGrants.includes(req.payload.grant_type))) {
323
+ return h.response({ error: 'unsupported_grant_type', error_description: `Request does not support the 'grant_type' '${req.payload.grant_type}'.` }).code(400);
324
+ }
325
+ // Client authentication is present?
326
+ const { clientId, clientSecret, error, errorDescription } = yield this._extractClientParams(req, authMethodsInstances, supported);
327
+ if (error) {
328
+ return h.response({ error: error, error_description: errorDescription || undefined }).code(400);
329
+ }
330
+ if (!clientId) {
331
+ return h
332
+ .response({
333
+ error: 'invalid_request',
334
+ error_description: `Supported token endpoint authentication methods: ${supported.join(', ')}`
335
+ }).code(400);
336
+ }
337
+ const hasRefreshToken = req.payload.refresh_token && typeof req.payload.refresh_token === 'string';
338
+ const isRefreshTokenGrantType = req.payload.grant_type === 'refresh_token';
339
+ if (clientId &&
340
+ hasRefreshToken &&
341
+ isRefreshTokenGrantType) {
342
+ const params = {
343
+ clientId,
344
+ grantType: `${req.payload.grant_type}`,
345
+ refreshToken: `${req.payload.refresh_token}`,
346
+ ttl: this.jwksGenerator.ttl,
347
+ createIDToken: hasOpenIDScope() ? ((payload) => tslib_1.__awaiter(this, void 0, void 0, function* () {
348
+ var _a;
349
+ return yield (0, jwks_generator_1.createIDToken)(this.jwksGenerator, Object.assign({ aud: clientId, iss: ((_a = t.postman) === null || _a === void 0 ? void 0 : _a.getHost()[0]) || '' }, payload));
350
+ })) : undefined
351
+ };
352
+ if (clientSecret) {
353
+ params.clientSecret = clientSecret;
354
+ }
355
+ if (req.payload.scope && typeof req.payload.scope === 'string') {
356
+ params.scope = req.payload.scope;
357
+ }
358
+ return (_a = this.refreshTokenRoute) === null || _a === void 0 ? void 0 : _a.handler(params, req, h);
359
+ }
360
+ else {
361
+ let error = 'unauthorized_client';
362
+ let errorDescription = '';
363
+ if (!clientId) {
364
+ error = 'invalid_request';
365
+ errorDescription = 'Request was missing the \'client_id\' parameter.';
366
+ }
367
+ else if (!(req.payload.refresh_token && typeof req.payload.refresh_token === 'string')) {
368
+ error = 'invalid_request';
369
+ errorDescription = 'Request was missing the \'refresh_token\' parameter.';
370
+ }
371
+ return h.response({ error, error_description: errorDescription }).code(400);
372
+ }
373
+ })
374
+ });
375
+ }
376
+ }
377
+ }
378
+ exports.OAuth2AuthorizationCode = OAuth2AuthorizationCode;
379
+ //#endregion OAuth2AuthorizationCode
380
+ //# sourceMappingURL=authentication-code.js.map