@adonisjs/ally 5.0.0-5 → 5.0.0-7
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.
- package/README.md +3 -6
- package/build/chunk-CSAU5B4Q.js +10 -0
- package/build/chunk-CSAU5B4Q.js.map +1 -0
- package/build/chunk-OSVNBZ7V.js +164 -0
- package/build/chunk-OSVNBZ7V.js.map +1 -0
- package/build/chunk-UF7PETXM.js +83 -0
- package/build/chunk-UF7PETXM.js.map +1 -0
- package/build/chunk-UIZWPBWM.js +38 -0
- package/build/chunk-UIZWPBWM.js.map +1 -0
- package/build/chunk-Y3GA4Y2H.js +170 -0
- package/build/chunk-Y3GA4Y2H.js.map +1 -0
- package/build/{stubs/config.stub → config.stub} +6 -7
- package/build/discord-NGJGLGX7.js +136 -0
- package/build/discord-NGJGLGX7.js.map +1 -0
- package/build/facebook-WTZGLDH5.js +137 -0
- package/build/facebook-WTZGLDH5.js.map +1 -0
- package/build/github-24BPMULZ.js +173 -0
- package/build/github-24BPMULZ.js.map +1 -0
- package/build/google-NMLTQESR.js +184 -0
- package/build/google-NMLTQESR.js.map +1 -0
- package/build/index.d.ts +3 -5
- package/build/index.js +128 -19
- package/build/index.js.map +1 -0
- package/build/linked_in-HIRSEAEP.js +153 -0
- package/build/linked_in-HIRSEAEP.js.map +1 -0
- package/build/providers/ally_provider.d.ts +6 -0
- package/build/providers/ally_provider.js +33 -23
- package/build/providers/ally_provider.js.map +1 -0
- package/build/spotify-ESJDFUD6.js +118 -0
- package/build/spotify-ESJDFUD6.js.map +1 -0
- package/build/src/abstract_drivers/oauth1.d.ts +1 -1
- package/build/src/abstract_drivers/oauth2.d.ts +1 -1
- package/build/src/debug.d.ts +1 -1
- package/build/src/define_config.d.ts +29 -10
- package/build/src/drivers/discord.d.ts +4 -3
- package/build/src/drivers/facebook.d.ts +4 -3
- package/build/src/drivers/github.d.ts +4 -3
- package/build/src/drivers/google.d.ts +4 -3
- package/build/src/drivers/linked_in.d.ts +4 -3
- package/build/src/drivers/spotify.d.ts +4 -3
- package/build/src/drivers/twitter.d.ts +2 -2
- package/build/src/types.d.ts +15 -44
- package/build/twitter-QISDDK24.js +101 -0
- package/build/twitter-QISDDK24.js.map +1 -0
- package/package.json +43 -31
- package/build/configure.js +0 -48
- package/build/src/abstract_drivers/oauth1.js +0 -188
- package/build/src/abstract_drivers/oauth2.js +0 -175
- package/build/src/ally_manager.js +0 -40
- package/build/src/bindings/http_context.d.ts +0 -6
- package/build/src/bindings/http_context.js +0 -19
- package/build/src/bindings/types.d.ts +0 -12
- package/build/src/bindings/types.js +0 -9
- package/build/src/debug.js +0 -10
- package/build/src/defaults/config.d.ts +0 -50
- package/build/src/defaults/config.js +0 -58
- package/build/src/define_config.js +0 -31
- package/build/src/drivers/discord.js +0 -156
- package/build/src/drivers/facebook.js +0 -155
- package/build/src/drivers/github.js +0 -213
- package/build/src/drivers/google.js +0 -197
- package/build/src/drivers/linked_in.js +0 -166
- package/build/src/drivers/spotify.js +0 -130
- package/build/src/drivers/twitter.js +0 -117
- package/build/src/drivers_collection.d.ts +0 -23
- package/build/src/drivers_collection.js +0 -72
- package/build/src/errors.js +0 -11
- package/build/src/redirect_request.js +0 -63
- package/build/src/types.js +0 -9
- package/build/stubs/main.js +0 -10
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
<br />
|
|
4
4
|
|
|
5
|
-
[![gh-workflow-image]][gh-workflow-url] [![npm-image]][npm-url] ![][typescript-image] [![license-image]][license-url]
|
|
5
|
+
[![gh-workflow-image]][gh-workflow-url] [![npm-image]][npm-url] ![][typescript-image] [![license-image]][license-url]
|
|
6
6
|
|
|
7
7
|
## Introduction
|
|
8
8
|
Social authentication provider for AdonisJS. Supports *Github*, Google, Twitter, Facebook, Discord, Spotify, and LinkedIn.
|
|
@@ -21,8 +21,8 @@ In order to ensure that the AdonisJS community is welcoming to all, please revie
|
|
|
21
21
|
## License
|
|
22
22
|
AdonisJS ally is open-sourced software licensed under the [MIT license](LICENSE.md).
|
|
23
23
|
|
|
24
|
-
[gh-workflow-image]: https://img.shields.io/github/actions/workflow/status/adonisjs/ally/
|
|
25
|
-
[gh-workflow-url]: https://github.com/adonisjs/ally/actions/workflows/
|
|
24
|
+
[gh-workflow-image]: https://img.shields.io/github/actions/workflow/status/adonisjs/ally/checks.yml?style=for-the-badge
|
|
25
|
+
[gh-workflow-url]: https://github.com/adonisjs/ally/actions/workflows/checks.yml "Github action"
|
|
26
26
|
|
|
27
27
|
[npm-image]: https://img.shields.io/npm/v/@adonisjs/ally/latest.svg?style=for-the-badge&logo=npm
|
|
28
28
|
[npm-url]: https://www.npmjs.com/package/@adonisjs/ally/v/latest "npm"
|
|
@@ -31,6 +31,3 @@ AdonisJS ally is open-sourced software licensed under the [MIT license](LICENSE.
|
|
|
31
31
|
|
|
32
32
|
[license-url]: LICENSE.md
|
|
33
33
|
[license-image]: https://img.shields.io/github/license/adonisjs/ally?style=for-the-badge
|
|
34
|
-
|
|
35
|
-
[snyk-image]: https://img.shields.io/snyk/vulnerabilities/github/adonisjs/ally?label=Snyk%20Vulnerabilities&style=for-the-badge
|
|
36
|
-
[snyk-url]: https://snyk.io/test/github/adonisjs/ally?targetFile=package.json "snyk"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import {
|
|
2
|
+
E_OAUTH_MISSING_CODE,
|
|
3
|
+
E_OAUTH_STATE_MISMATCH,
|
|
4
|
+
RedirectRequest
|
|
5
|
+
} from "./chunk-UF7PETXM.js";
|
|
6
|
+
|
|
7
|
+
// src/abstract_drivers/oauth2.ts
|
|
8
|
+
import { Exception } from "@poppinss/utils";
|
|
9
|
+
import { Oauth2Client } from "@poppinss/oauth-client/oauth2";
|
|
10
|
+
var Oauth2Driver = class extends Oauth2Client {
|
|
11
|
+
constructor(ctx, config) {
|
|
12
|
+
super(config);
|
|
13
|
+
this.ctx = ctx;
|
|
14
|
+
this.config = config;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Is the authorization process stateless?
|
|
18
|
+
*/
|
|
19
|
+
isStateless = false;
|
|
20
|
+
/**
|
|
21
|
+
* Oauth client version
|
|
22
|
+
*/
|
|
23
|
+
version = "oauth2";
|
|
24
|
+
/**
|
|
25
|
+
* The value of state read from the cookies.
|
|
26
|
+
*/
|
|
27
|
+
stateCookieValue;
|
|
28
|
+
/**
|
|
29
|
+
* The Oauth2Client will use the instance returned from this method to
|
|
30
|
+
* build the redirect url
|
|
31
|
+
*/
|
|
32
|
+
urlBuilder(url) {
|
|
33
|
+
return new RedirectRequest(url, this.scopeParamName, this.scopesSeparator);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Loads the value of state from the cookie and removes it right
|
|
37
|
+
* away. We read the cookie value and clear it during the
|
|
38
|
+
* current request lifecycle.
|
|
39
|
+
*
|
|
40
|
+
* :::::
|
|
41
|
+
* NOTE
|
|
42
|
+
* :::::
|
|
43
|
+
*
|
|
44
|
+
* This child class must call this method inside the constructor.
|
|
45
|
+
*/
|
|
46
|
+
loadState() {
|
|
47
|
+
if (this.isStateless) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
this.stateCookieValue = this.ctx.request.encryptedCookie(this.stateCookieName);
|
|
51
|
+
this.ctx.response.clearCookie(this.stateCookieName);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Persists the state inside the cookie
|
|
55
|
+
*/
|
|
56
|
+
#persistState() {
|
|
57
|
+
if (this.isStateless) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const state = this.getState();
|
|
61
|
+
this.ctx.response.encryptedCookie(this.stateCookieName, state, {
|
|
62
|
+
sameSite: false,
|
|
63
|
+
httpOnly: true
|
|
64
|
+
});
|
|
65
|
+
return state;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Perform stateless authentication. Only applicable for Oauth2 client
|
|
69
|
+
*/
|
|
70
|
+
stateless() {
|
|
71
|
+
this.isStateless = true;
|
|
72
|
+
return this;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Returns the redirect URL for the request.
|
|
76
|
+
*/
|
|
77
|
+
async redirectUrl(callback) {
|
|
78
|
+
const url = this.getRedirectUrl(callback);
|
|
79
|
+
return url;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Redirect user for authorization.
|
|
83
|
+
*/
|
|
84
|
+
async redirect(callback) {
|
|
85
|
+
const url = await this.redirectUrl((request) => {
|
|
86
|
+
const state = this.#persistState();
|
|
87
|
+
state && request.param(this.stateParamName, state);
|
|
88
|
+
if (typeof callback === "function") {
|
|
89
|
+
callback(request);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
this.ctx.response.redirect(url);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Find if there is a state mismatch
|
|
96
|
+
*/
|
|
97
|
+
stateMisMatch() {
|
|
98
|
+
if (this.isStateless) {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
return this.stateCookieValue !== this.ctx.request.input(this.stateParamName);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Find if there is an error post redirect
|
|
105
|
+
*/
|
|
106
|
+
hasError() {
|
|
107
|
+
return !!this.getError();
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Get the post redirect error
|
|
111
|
+
*/
|
|
112
|
+
getError() {
|
|
113
|
+
const error = this.ctx.request.input(this.errorParamName);
|
|
114
|
+
if (error) {
|
|
115
|
+
return error;
|
|
116
|
+
}
|
|
117
|
+
if (!this.hasCode()) {
|
|
118
|
+
return "unknown_error";
|
|
119
|
+
}
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Returns the authorization code
|
|
124
|
+
*/
|
|
125
|
+
getCode() {
|
|
126
|
+
return this.ctx.request.input(this.codeParamName, null);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Find it the code exists
|
|
130
|
+
*/
|
|
131
|
+
hasCode() {
|
|
132
|
+
return !!this.getCode();
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Get access token
|
|
136
|
+
*/
|
|
137
|
+
async accessToken(callback) {
|
|
138
|
+
if (this.hasError()) {
|
|
139
|
+
throw new E_OAUTH_MISSING_CODE([this.codeParamName]);
|
|
140
|
+
}
|
|
141
|
+
if (this.stateMisMatch()) {
|
|
142
|
+
throw new E_OAUTH_STATE_MISMATCH();
|
|
143
|
+
}
|
|
144
|
+
return this.getAccessToken((request) => {
|
|
145
|
+
request.field(this.codeParamName, this.getCode());
|
|
146
|
+
if (typeof callback === "function") {
|
|
147
|
+
callback(request);
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Not applicable with Oauth2
|
|
153
|
+
*/
|
|
154
|
+
async userFromTokenAndSecret() {
|
|
155
|
+
throw new Exception(
|
|
156
|
+
'"userFromTokenAndSecret" is not applicable with Oauth2. Use "userFromToken" instead'
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
export {
|
|
162
|
+
Oauth2Driver
|
|
163
|
+
};
|
|
164
|
+
//# sourceMappingURL=chunk-OSVNBZ7V.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/abstract_drivers/oauth2.ts"],"sourcesContent":["/*\n * @adonisjs/ally\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { Exception } from '@poppinss/utils'\nimport type { HttpContext } from '@adonisjs/core/http'\nimport { Oauth2Client } from '@poppinss/oauth-client/oauth2'\n\nimport {\n AllyUserContract,\n Oauth2AccessToken,\n Oauth2DriverConfig,\n ApiRequestContract,\n AllyDriverContract,\n RedirectRequestContract,\n} from '../types.js'\n\nimport * as errors from '../errors.js'\nimport { RedirectRequest } from '../redirect_request.js'\n\n/**\n * Abstract implementation for an Oauth2 driver\n */\nexport abstract class Oauth2Driver<Token extends Oauth2AccessToken, Scopes extends string>\n extends Oauth2Client<Token>\n implements AllyDriverContract<Token, Scopes>\n{\n /**\n * Is the authorization process stateless?\n */\n protected isStateless: boolean = false\n\n /**\n * The cookie name for storing the CSRF token. Must be unique for your\n * driver. One option is to prefix the driver name. For example:\n * `gh_oauth_state`\n */\n protected abstract stateCookieName: string\n\n /**\n * The parameter in which to send the state to the oauth provider. The same\n * input is used to retrieve the state post redirect as well.\n *\n * You must check the auth provider docs to find it\n */\n protected abstract stateParamName: string\n\n /**\n * The parameter name from which to fetch the error message or error code\n * post redirect.\n *\n * You must check the auth provider docs to find it\n */\n protected abstract errorParamName: string\n\n /**\n * The parameter name from which to fetch the authorization code. It is usually\n * named as \"code\".\n *\n * You must check the auth provider docs to find it\n */\n protected abstract codeParamName: string\n\n /**\n * Authorization URL for the auth provider. The user will be redirected\n * to this URL\n */\n protected abstract authorizeUrl: string\n\n /**\n * The URL to hit to get an access token\n */\n protected abstract accessTokenUrl: string\n\n /**\n * The query param name for defining the Authorization scopes.\n * Mostly it is `scope`\n */\n protected abstract scopeParamName: string\n\n /**\n * The identifier for joining multiple scopes. Mostly it is a space.\n */\n protected abstract scopesSeparator: string\n\n /**\n * Returns details for the authorized user\n */\n abstract user(callback?: (request: ApiRequestContract) => void): Promise<AllyUserContract<Token>>\n\n /**\n * Finds the user by access token\n */\n abstract userFromToken(\n token: string,\n callback?: (request: ApiRequestContract) => void\n ): Promise<AllyUserContract<{ token: string; type: 'bearer' }>>\n\n /**\n * Find if the current error code is for access denied\n */\n abstract accessDenied(): boolean\n\n /**\n * Oauth client version\n */\n version = 'oauth2' as const\n\n /**\n * The value of state read from the cookies.\n */\n protected stateCookieValue?: string\n\n constructor(\n protected ctx: HttpContext,\n public config: Oauth2DriverConfig\n ) {\n super(config)\n }\n\n /**\n * The Oauth2Client will use the instance returned from this method to\n * build the redirect url\n */\n protected urlBuilder(url: string) {\n return new RedirectRequest(url, this.scopeParamName, this.scopesSeparator)\n }\n\n /**\n * Loads the value of state from the cookie and removes it right\n * away. We read the cookie value and clear it during the\n * current request lifecycle.\n *\n * :::::\n * NOTE\n * :::::\n *\n * This child class must call this method inside the constructor.\n */\n protected loadState() {\n if (this.isStateless) {\n return\n }\n\n this.stateCookieValue = this.ctx.request.encryptedCookie(this.stateCookieName)\n this.ctx.response.clearCookie(this.stateCookieName)\n }\n\n /**\n * Persists the state inside the cookie\n */\n #persistState(): string | undefined {\n if (this.isStateless) {\n return\n }\n\n const state = this.getState()\n this.ctx.response.encryptedCookie(this.stateCookieName, state, {\n sameSite: false,\n httpOnly: true,\n })\n\n return state\n }\n\n /**\n * Perform stateless authentication. Only applicable for Oauth2 client\n */\n stateless(): this {\n this.isStateless = true\n return this\n }\n\n /**\n * Returns the redirect URL for the request.\n */\n async redirectUrl(\n callback?: (request: RedirectRequestContract<Scopes>) => void\n ): Promise<string> {\n const url = this.getRedirectUrl(callback as any)\n return url\n }\n\n /**\n * Redirect user for authorization.\n */\n async redirect(callback?: (request: RedirectRequestContract<Scopes>) => void): Promise<void> {\n const url = await this.redirectUrl((request) => {\n const state = this.#persistState()\n state && request.param(this.stateParamName, state)\n\n if (typeof callback === 'function') {\n callback(request)\n }\n })\n\n this.ctx.response.redirect(url)\n }\n\n /**\n * Find if there is a state mismatch\n */\n stateMisMatch(): boolean {\n if (this.isStateless) {\n return false\n }\n\n return this.stateCookieValue !== this.ctx.request.input(this.stateParamName)\n }\n\n /**\n * Find if there is an error post redirect\n */\n hasError(): boolean {\n return !!this.getError()\n }\n\n /**\n * Get the post redirect error\n */\n getError(): string | null {\n const error = this.ctx.request.input(this.errorParamName)\n if (error) {\n return error\n }\n\n if (!this.hasCode()) {\n return 'unknown_error'\n }\n\n return null\n }\n\n /**\n * Returns the authorization code\n */\n getCode(): string | null {\n return this.ctx.request.input(this.codeParamName, null)\n }\n\n /**\n * Find it the code exists\n */\n hasCode(): boolean {\n return !!this.getCode()\n }\n\n /**\n * Get access token\n */\n async accessToken(callback?: (request: ApiRequestContract) => void): Promise<Token> {\n /**\n * We expect the user to handle errors before calling this method\n */\n if (this.hasError()) {\n throw new errors.E_OAUTH_MISSING_CODE([this.codeParamName])\n }\n\n /**\n * We expect the user to properly handle the state mis-match use case before\n * calling this method\n */\n if (this.stateMisMatch()) {\n throw new errors.E_OAUTH_STATE_MISMATCH()\n }\n\n /**\n * Get access token by providing the authorization code\n */\n return this.getAccessToken((request) => {\n request.field(this.codeParamName, this.getCode())\n\n if (typeof callback === 'function') {\n callback(request)\n }\n })\n }\n\n /**\n * Not applicable with Oauth2\n */\n async userFromTokenAndSecret(): Promise<never> {\n throw new Exception(\n '\"userFromTokenAndSecret\" is not applicable with Oauth2. Use \"userFromToken\" instead'\n )\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__export
|
|
3
|
+
} from "./chunk-CSAU5B4Q.js";
|
|
4
|
+
|
|
5
|
+
// src/errors.ts
|
|
6
|
+
var errors_exports = {};
|
|
7
|
+
__export(errors_exports, {
|
|
8
|
+
E_OAUTH_MISSING_CODE: () => E_OAUTH_MISSING_CODE,
|
|
9
|
+
E_OAUTH_STATE_MISMATCH: () => E_OAUTH_STATE_MISMATCH
|
|
10
|
+
});
|
|
11
|
+
import { createError } from "@poppinss/utils";
|
|
12
|
+
var E_OAUTH_MISSING_CODE = createError(
|
|
13
|
+
'Cannot request access token. Redirect request is missing the "%s" param',
|
|
14
|
+
"E_OAUTH_MISSING_CODE",
|
|
15
|
+
500
|
|
16
|
+
);
|
|
17
|
+
var E_OAUTH_STATE_MISMATCH = createError(
|
|
18
|
+
"Unable to verify re-redirect state",
|
|
19
|
+
"E_OAUTH_STATE_MISMATCH",
|
|
20
|
+
400
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
// src/redirect_request.ts
|
|
24
|
+
import { UrlBuilder } from "@poppinss/oauth-client";
|
|
25
|
+
var RedirectRequest = class extends UrlBuilder {
|
|
26
|
+
#scopesTransformer;
|
|
27
|
+
#scopeParamName;
|
|
28
|
+
#scopeSeparator;
|
|
29
|
+
constructor(baseUrl, scopeParamName, scopeSeparator) {
|
|
30
|
+
super(baseUrl);
|
|
31
|
+
this.#scopeParamName = scopeParamName;
|
|
32
|
+
this.#scopeSeparator = scopeSeparator;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Register a custom function to transform scopes. Exposed for drivers
|
|
36
|
+
* to implement.
|
|
37
|
+
*/
|
|
38
|
+
transformScopes(callback) {
|
|
39
|
+
this.#scopesTransformer = callback;
|
|
40
|
+
return this;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Define an array of scopes.
|
|
44
|
+
*/
|
|
45
|
+
scopes(scopes) {
|
|
46
|
+
if (typeof this.#scopesTransformer === "function") {
|
|
47
|
+
scopes = this.#scopesTransformer(scopes);
|
|
48
|
+
}
|
|
49
|
+
this.param(this.#scopeParamName, scopes.join(this.#scopeSeparator));
|
|
50
|
+
return this;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Merge to existing scopes
|
|
54
|
+
*/
|
|
55
|
+
mergeScopes(scopes) {
|
|
56
|
+
if (typeof this.#scopesTransformer === "function") {
|
|
57
|
+
scopes = this.#scopesTransformer(scopes);
|
|
58
|
+
}
|
|
59
|
+
const existingScopes = this.getParams()[this.#scopeParamName];
|
|
60
|
+
const scopesString = scopes.join(this.#scopeSeparator);
|
|
61
|
+
if (!existingScopes) {
|
|
62
|
+
this.param(this.#scopeParamName, scopesString);
|
|
63
|
+
return this;
|
|
64
|
+
}
|
|
65
|
+
this.param(this.#scopeParamName, `${existingScopes}${this.#scopeSeparator}${scopesString}`);
|
|
66
|
+
return this;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Clear existing scopes
|
|
70
|
+
*/
|
|
71
|
+
clearScopes() {
|
|
72
|
+
this.clearParam(this.#scopeParamName);
|
|
73
|
+
return this;
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export {
|
|
78
|
+
E_OAUTH_MISSING_CODE,
|
|
79
|
+
E_OAUTH_STATE_MISMATCH,
|
|
80
|
+
errors_exports,
|
|
81
|
+
RedirectRequest
|
|
82
|
+
};
|
|
83
|
+
//# sourceMappingURL=chunk-UF7PETXM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/redirect_request.ts"],"sourcesContent":["/*\n * @adonisjs/ally\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { createError } from '@poppinss/utils'\n\nexport const E_OAUTH_MISSING_CODE = createError<[string]>(\n 'Cannot request access token. Redirect request is missing the \"%s\" param',\n 'E_OAUTH_MISSING_CODE',\n 500\n)\n\nexport const E_OAUTH_STATE_MISMATCH = createError(\n 'Unable to verify re-redirect state',\n 'E_OAUTH_STATE_MISMATCH',\n 400\n)\n","/*\n * @adonisjs/ally\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { UrlBuilder } from '@poppinss/oauth-client'\nimport { LiteralStringUnion } from './types.js'\n\n/**\n * Redirect request with first class support for defining scopes.\n */\nexport class RedirectRequest<Scopes extends string> extends UrlBuilder {\n #scopesTransformer: undefined | ((scopes: LiteralStringUnion<Scopes>[]) => string[])\n #scopeParamName: string\n #scopeSeparator: string\n\n constructor(baseUrl: string, scopeParamName: string, scopeSeparator: string) {\n super(baseUrl)\n this.#scopeParamName = scopeParamName\n this.#scopeSeparator = scopeSeparator\n }\n\n /**\n * Register a custom function to transform scopes. Exposed for drivers\n * to implement.\n */\n transformScopes(callback: (scopes: LiteralStringUnion<Scopes>[]) => string[]): this {\n this.#scopesTransformer = callback\n return this\n }\n\n /**\n * Define an array of scopes.\n */\n scopes(scopes: LiteralStringUnion<Scopes>[]): this {\n if (typeof this.#scopesTransformer === 'function') {\n scopes = this.#scopesTransformer(scopes)\n }\n\n this.param(this.#scopeParamName, scopes.join(this.#scopeSeparator))\n return this\n }\n\n /**\n * Merge to existing scopes\n */\n mergeScopes(scopes: LiteralStringUnion<Scopes>[]): this {\n if (typeof this.#scopesTransformer === 'function') {\n scopes = this.#scopesTransformer(scopes)\n }\n\n const existingScopes = this.getParams()[this.#scopeParamName]\n const scopesString = scopes.join(this.#scopeSeparator)\n\n if (!existingScopes) {\n this.param(this.#scopeParamName, scopesString)\n return this\n }\n\n this.param(this.#scopeParamName, `${existingScopes}${this.#scopeSeparator}${scopesString}`)\n return this\n }\n\n /**\n * Clear existing scopes\n */\n clearScopes(): this {\n this.clearParam(this.#scopeParamName)\n return this\n }\n}\n"],"mappings":";;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AASA,SAAS,mBAAmB;AAErB,IAAM,uBAAuB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,yBAAyB;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AACF;;;ACZA,SAAS,kBAAkB;AAMpB,IAAM,kBAAN,cAAqD,WAAW;AAAA,EACrE;AAAA,EACA;AAAA,EACA;AAAA,EAEA,YAAY,SAAiB,gBAAwB,gBAAwB;AAC3E,UAAM,OAAO;AACb,SAAK,kBAAkB;AACvB,SAAK,kBAAkB;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAgB,UAAoE;AAClF,SAAK,qBAAqB;AAC1B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,QAA4C;AACjD,QAAI,OAAO,KAAK,uBAAuB,YAAY;AACjD,eAAS,KAAK,mBAAmB,MAAM;AAAA,IACzC;AAEA,SAAK,MAAM,KAAK,iBAAiB,OAAO,KAAK,KAAK,eAAe,CAAC;AAClE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,QAA4C;AACtD,QAAI,OAAO,KAAK,uBAAuB,YAAY;AACjD,eAAS,KAAK,mBAAmB,MAAM;AAAA,IACzC;AAEA,UAAM,iBAAiB,KAAK,UAAU,EAAE,KAAK,eAAe;AAC5D,UAAM,eAAe,OAAO,KAAK,KAAK,eAAe;AAErD,QAAI,CAAC,gBAAgB;AACnB,WAAK,MAAM,KAAK,iBAAiB,YAAY;AAC7C,aAAO;AAAA,IACT;AAEA,SAAK,MAAM,KAAK,iBAAiB,GAAG,cAAc,GAAG,KAAK,eAAe,GAAG,YAAY,EAAE;AAC1F,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,cAAoB;AAClB,SAAK,WAAW,KAAK,eAAe;AACpC,WAAO;AAAA,EACT;AACF;","names":[]}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// src/ally_manager.ts
|
|
2
|
+
import { RuntimeException } from "@poppinss/utils";
|
|
3
|
+
var AllyManager = class {
|
|
4
|
+
/**
|
|
5
|
+
* Config with the list of social providers
|
|
6
|
+
*/
|
|
7
|
+
#config;
|
|
8
|
+
#ctx;
|
|
9
|
+
#driversCache = /* @__PURE__ */ new Map();
|
|
10
|
+
constructor(config, ctx) {
|
|
11
|
+
this.#ctx = ctx;
|
|
12
|
+
this.#config = config;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Returns the driver instance of a social provider
|
|
16
|
+
*/
|
|
17
|
+
use(provider) {
|
|
18
|
+
if (this.#driversCache.has(provider)) {
|
|
19
|
+
return this.#driversCache.get(provider);
|
|
20
|
+
}
|
|
21
|
+
const driver = this.#config[provider];
|
|
22
|
+
if (!driver) {
|
|
23
|
+
throw new RuntimeException(
|
|
24
|
+
`Unknown ally provider "${String(
|
|
25
|
+
provider
|
|
26
|
+
)}". Make sure it is registered inside the config/ally.ts file`
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
const driverInstance = driver(this.#ctx);
|
|
30
|
+
this.#driversCache.set(provider, driverInstance);
|
|
31
|
+
return driverInstance;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export {
|
|
36
|
+
AllyManager
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=chunk-UIZWPBWM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ally_manager.ts"],"sourcesContent":["/*\n * @adonisjs/ally\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { RuntimeException } from '@poppinss/utils'\nimport type { HttpContext } from '@adonisjs/core/http'\nimport type { AllyDriverContract, AllyManagerDriverFactory } from './types.js'\n\n/**\n * AllyManager is used to create instances of a social drivers during an\n * HTTP request. The drivers are cached during the lifecycle of a request.\n */\nexport class AllyManager<KnownSocialProviders extends Record<string, AllyManagerDriverFactory>> {\n /**\n * Config with the list of social providers\n */\n #config: KnownSocialProviders\n #ctx: HttpContext\n #driversCache: Map<keyof KnownSocialProviders, AllyDriverContract<any, any>> = new Map()\n\n constructor(config: KnownSocialProviders, ctx: HttpContext) {\n this.#ctx = ctx\n this.#config = config\n }\n\n /**\n * Returns the driver instance of a social provider\n */\n use<SocialProvider extends keyof KnownSocialProviders>(\n provider: SocialProvider\n ): ReturnType<KnownSocialProviders[SocialProvider]> {\n if (this.#driversCache.has(provider)) {\n return this.#driversCache.get(provider) as ReturnType<KnownSocialProviders[SocialProvider]>\n }\n\n const driver = this.#config[provider]\n if (!driver) {\n throw new RuntimeException(\n `Unknown ally provider \"${String(\n provider\n )}\". Make sure it is registered inside the config/ally.ts file`\n )\n }\n\n const driverInstance = driver(this.#ctx) as ReturnType<KnownSocialProviders[SocialProvider]>\n this.#driversCache.set(provider, driverInstance)\n\n return driverInstance\n }\n}\n"],"mappings":";AASA,SAAS,wBAAwB;AAQ1B,IAAM,cAAN,MAAyF;AAAA;AAAA;AAAA;AAAA,EAI9F;AAAA,EACA;AAAA,EACA,gBAA+E,oBAAI,IAAI;AAAA,EAEvF,YAAY,QAA8B,KAAkB;AAC1D,SAAK,OAAO;AACZ,SAAK,UAAU;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA,EAKA,IACE,UACkD;AAClD,QAAI,KAAK,cAAc,IAAI,QAAQ,GAAG;AACpC,aAAO,KAAK,cAAc,IAAI,QAAQ;AAAA,IACxC;AAEA,UAAM,SAAS,KAAK,QAAQ,QAAQ;AACpC,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI;AAAA,QACR,0BAA0B;AAAA,UACxB;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAEA,UAAM,iBAAiB,OAAO,KAAK,IAAI;AACvC,SAAK,cAAc,IAAI,UAAU,cAAc;AAE/C,WAAO;AAAA,EACT;AACF;","names":[]}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import {
|
|
2
|
+
E_OAUTH_MISSING_CODE,
|
|
3
|
+
E_OAUTH_STATE_MISMATCH,
|
|
4
|
+
RedirectRequest
|
|
5
|
+
} from "./chunk-UF7PETXM.js";
|
|
6
|
+
|
|
7
|
+
// src/abstract_drivers/oauth1.ts
|
|
8
|
+
import { Exception } from "@poppinss/utils";
|
|
9
|
+
import { Oauth1Client } from "@poppinss/oauth-client/oauth1";
|
|
10
|
+
var Oauth1Driver = class extends Oauth1Client {
|
|
11
|
+
constructor(ctx, config) {
|
|
12
|
+
super(config);
|
|
13
|
+
this.ctx = ctx;
|
|
14
|
+
this.config = config;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Oauth client version
|
|
18
|
+
*/
|
|
19
|
+
version = "oauth1";
|
|
20
|
+
/**
|
|
21
|
+
* The value of "oauth_token" and "oauth_secret" from the cookies
|
|
22
|
+
*/
|
|
23
|
+
oauthTokenCookieValue;
|
|
24
|
+
oauthSecretCookieValue;
|
|
25
|
+
/**
|
|
26
|
+
* The cookie name for storing the secret
|
|
27
|
+
*/
|
|
28
|
+
get oauthSecretCookieName() {
|
|
29
|
+
return `${this.oauthTokenCookieName}_secret`;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The Oauth1Client will use the instance returned from this method to
|
|
33
|
+
* build the redirect url
|
|
34
|
+
*/
|
|
35
|
+
urlBuilder(url) {
|
|
36
|
+
return new RedirectRequest(url, this.scopeParamName, this.scopesSeparator);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Loads the value of state from the cookie and removes it right
|
|
40
|
+
* away. We read the cookie value and clear it during the
|
|
41
|
+
* current request lifecycle.
|
|
42
|
+
*
|
|
43
|
+
* :::::
|
|
44
|
+
* NOTE
|
|
45
|
+
* :::::
|
|
46
|
+
*
|
|
47
|
+
* This child class must call this method inside the constructor.
|
|
48
|
+
*/
|
|
49
|
+
loadState() {
|
|
50
|
+
this.oauthTokenCookieValue = this.ctx.request.encryptedCookie(this.oauthTokenCookieName);
|
|
51
|
+
this.oauthSecretCookieValue = this.ctx.request.encryptedCookie(this.oauthSecretCookieName);
|
|
52
|
+
this.ctx.response.clearCookie(this.oauthTokenCookieName);
|
|
53
|
+
this.ctx.response.clearCookie(this.oauthSecretCookieName);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Persists the token (aka state) inside the cookie
|
|
57
|
+
*/
|
|
58
|
+
#persistToken(token) {
|
|
59
|
+
this.ctx.response.encryptedCookie(this.oauthTokenCookieName, token, {
|
|
60
|
+
sameSite: false,
|
|
61
|
+
httpOnly: true
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Persists the secret inside the cookie
|
|
66
|
+
*/
|
|
67
|
+
#persistSecret(secret) {
|
|
68
|
+
this.ctx.response.encryptedCookie(this.oauthSecretCookieName, secret, {
|
|
69
|
+
sameSite: false,
|
|
70
|
+
httpOnly: true
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Perform stateless authentication. Only applicable for Oauth1 client
|
|
75
|
+
*/
|
|
76
|
+
stateless() {
|
|
77
|
+
throw new Exception("OAuth1 does not support stateless authorization");
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Returns the redirect URL for the request.
|
|
81
|
+
*/
|
|
82
|
+
async redirectUrl(callback) {
|
|
83
|
+
return this.getRedirectUrl(callback);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Redirect user for authorization.
|
|
87
|
+
*/
|
|
88
|
+
async redirect(callback) {
|
|
89
|
+
const { token, secret } = await this.getRequestToken();
|
|
90
|
+
this.#persistToken(token);
|
|
91
|
+
this.#persistSecret(secret);
|
|
92
|
+
const url = await this.redirectUrl((request) => {
|
|
93
|
+
request.param(this.oauthTokenParamName, token);
|
|
94
|
+
if (typeof callback === "function") {
|
|
95
|
+
callback(request);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
this.ctx.response.redirect(url);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Find if there is a state mismatch
|
|
102
|
+
*/
|
|
103
|
+
stateMisMatch() {
|
|
104
|
+
return this.oauthTokenCookieValue !== this.ctx.request.input(this.oauthTokenParamName);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Find if there is an error post redirect
|
|
108
|
+
*/
|
|
109
|
+
hasError() {
|
|
110
|
+
return !!this.getError();
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Get the post redirect error
|
|
114
|
+
*/
|
|
115
|
+
getError() {
|
|
116
|
+
const error = this.ctx.request.input(this.errorParamName);
|
|
117
|
+
if (error) {
|
|
118
|
+
return error;
|
|
119
|
+
}
|
|
120
|
+
if (!this.hasCode()) {
|
|
121
|
+
return "unknown_error";
|
|
122
|
+
}
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Returns the "oauth_verifier" token
|
|
127
|
+
*/
|
|
128
|
+
getCode() {
|
|
129
|
+
return this.ctx.request.input(this.oauthTokenVerifierName, null);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Find it the code exists
|
|
133
|
+
*/
|
|
134
|
+
hasCode() {
|
|
135
|
+
return !!this.getCode();
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Get access token
|
|
139
|
+
*/
|
|
140
|
+
async accessToken(callback) {
|
|
141
|
+
if (this.hasError()) {
|
|
142
|
+
throw new E_OAUTH_MISSING_CODE([this.oauthTokenVerifierName]);
|
|
143
|
+
}
|
|
144
|
+
if (this.stateMisMatch()) {
|
|
145
|
+
throw new E_OAUTH_STATE_MISMATCH();
|
|
146
|
+
}
|
|
147
|
+
return this.getAccessToken(
|
|
148
|
+
{ token: this.oauthTokenCookieValue, secret: this.oauthSecretCookieValue },
|
|
149
|
+
(request) => {
|
|
150
|
+
request.oauth1Param(this.oauthTokenVerifierName, this.getCode());
|
|
151
|
+
if (typeof callback === "function") {
|
|
152
|
+
callback(request);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Not applicable with Oauth1
|
|
159
|
+
*/
|
|
160
|
+
async userFromToken() {
|
|
161
|
+
throw new Exception(
|
|
162
|
+
'"userFromToken" is not available with Oauth1. Use "userFromTokenAndSecret" instead'
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
export {
|
|
168
|
+
Oauth1Driver
|
|
169
|
+
};
|
|
170
|
+
//# sourceMappingURL=chunk-Y3GA4Y2H.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/abstract_drivers/oauth1.ts"],"sourcesContent":["/*\n * @adonisjs/ally\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport { Exception } from '@poppinss/utils'\nimport type { HttpContext } from '@adonisjs/core/http'\nimport { Oauth1Client } from '@poppinss/oauth-client/oauth1'\n\nimport {\n AllyUserContract,\n Oauth1AccessToken,\n Oauth1DriverConfig,\n ApiRequestContract,\n AllyDriverContract,\n RedirectRequestContract,\n} from '../types.js'\n\nimport * as errors from '../errors.js'\nimport { RedirectRequest } from '../redirect_request.js'\n\n/**\n * Abstract implementation for an Oauth1 driver\n */\nexport abstract class Oauth1Driver<Token extends Oauth1AccessToken, Scopes extends string>\n extends Oauth1Client<Token>\n implements AllyDriverContract<Token, Scopes>\n{\n /**\n * The cookie name for storing the \"oauth_token\". Must be unique for your\n * driver. One option is to prefix the driver name. For example:\n * `twitter_oauth_token`\n */\n protected abstract oauthTokenCookieName: string\n\n /**\n * Name of the \"oauth_token\" param. This is the query string value post\n * authorization redirect\n */\n protected abstract oauthTokenParamName: string\n\n /**\n * Name of the \"oauth_verifier\" param. This is the query string value post\n * authorization redirect\n */\n protected abstract oauthTokenVerifierName: string\n\n /**\n * The parameter name from which to fetch the error message or error code\n * post redirect.\n *\n * You must check the auth provider docs to find it\n */\n protected abstract errorParamName: string\n\n /**\n * Request token URL for the auth provider. The initial set of tokens\n * are generated from this url\n */\n protected abstract requestTokenUrl: string\n\n /**\n * Authorization URL for the auth provider. The user will be redirected\n * to this URL\n */\n protected abstract authorizeUrl: string\n\n /**\n * The URL to hit to get an access token\n */\n protected abstract accessTokenUrl: string\n\n /**\n * The query param name for defining the Authorization scopes.\n * Mostly it is `scope`. Leave to empty string when scopes\n * are not applicable\n */\n protected abstract scopeParamName: string\n\n /**\n * The identifier for joining multiple scopes. Mostly it is a space.\n */\n protected abstract scopesSeparator: string\n\n /**\n * Returns details for the authorized user\n */\n abstract user(callback?: (request: ApiRequestContract) => void): Promise<AllyUserContract<Token>>\n\n /**\n * Finds the user by access token\n */\n abstract userFromTokenAndSecret(\n token: string,\n secret: string,\n callback?: (request: ApiRequestContract) => void\n ): Promise<AllyUserContract<{ token: string; secret: string }>>\n\n /**\n * Find if the current error code is for access denied\n */\n abstract accessDenied(): boolean\n\n /**\n * Oauth client version\n */\n version = 'oauth1' as const\n\n /**\n * The value of \"oauth_token\" and \"oauth_secret\" from the cookies\n */\n protected oauthTokenCookieValue?: string\n protected oauthSecretCookieValue?: string\n\n /**\n * The cookie name for storing the secret\n */\n protected get oauthSecretCookieName() {\n return `${this.oauthTokenCookieName}_secret`\n }\n\n constructor(\n protected ctx: HttpContext,\n public config: Oauth1DriverConfig\n ) {\n super(config)\n }\n\n /**\n * The Oauth1Client will use the instance returned from this method to\n * build the redirect url\n */\n protected urlBuilder(url: string) {\n return new RedirectRequest(url, this.scopeParamName, this.scopesSeparator)\n }\n\n /**\n * Loads the value of state from the cookie and removes it right\n * away. We read the cookie value and clear it during the\n * current request lifecycle.\n *\n * :::::\n * NOTE\n * :::::\n *\n * This child class must call this method inside the constructor.\n */\n protected loadState() {\n /**\n * Read and cache in-memory\n */\n this.oauthTokenCookieValue = this.ctx.request.encryptedCookie(this.oauthTokenCookieName)\n this.oauthSecretCookieValue = this.ctx.request.encryptedCookie(this.oauthSecretCookieName)\n\n /**\n * Clear cookies\n */\n this.ctx.response.clearCookie(this.oauthTokenCookieName)\n this.ctx.response.clearCookie(this.oauthSecretCookieName)\n }\n\n /**\n * Persists the token (aka state) inside the cookie\n */\n #persistToken(token: string): void {\n this.ctx.response.encryptedCookie(this.oauthTokenCookieName, token, {\n sameSite: false,\n httpOnly: true,\n })\n }\n\n /**\n * Persists the secret inside the cookie\n */\n #persistSecret(secret: string): void {\n this.ctx.response.encryptedCookie(this.oauthSecretCookieName, secret, {\n sameSite: false,\n httpOnly: true,\n })\n }\n\n /**\n * Perform stateless authentication. Only applicable for Oauth1 client\n */\n stateless(): never {\n throw new Exception('OAuth1 does not support stateless authorization')\n }\n\n /**\n * Returns the redirect URL for the request.\n */\n async redirectUrl(\n callback?: (request: RedirectRequestContract<Scopes>) => void\n ): Promise<string> {\n return this.getRedirectUrl(callback as any)\n }\n\n /**\n * Redirect user for authorization.\n */\n async redirect(callback?: (request: RedirectRequestContract<Scopes>) => void): Promise<void> {\n const { token, secret } = await this.getRequestToken()\n\n /**\n * Storing token and secret inside cookies. We need them\n * later\n */\n this.#persistToken(token)\n this.#persistSecret(secret)\n\n const url = await this.redirectUrl((request) => {\n request.param(this.oauthTokenParamName, token)\n\n if (typeof callback === 'function') {\n callback(request)\n }\n })\n\n this.ctx.response.redirect(url)\n }\n\n /**\n * Find if there is a state mismatch\n */\n stateMisMatch(): boolean {\n return this.oauthTokenCookieValue !== this.ctx.request.input(this.oauthTokenParamName)\n }\n\n /**\n * Find if there is an error post redirect\n */\n hasError(): boolean {\n return !!this.getError()\n }\n\n /**\n * Get the post redirect error\n */\n getError(): string | null {\n const error = this.ctx.request.input(this.errorParamName)\n if (error) {\n return error\n }\n\n if (!this.hasCode()) {\n return 'unknown_error'\n }\n\n return null\n }\n\n /**\n * Returns the \"oauth_verifier\" token\n */\n getCode(): string | null {\n return this.ctx.request.input(this.oauthTokenVerifierName, null)\n }\n\n /**\n * Find it the code exists\n */\n hasCode(): boolean {\n return !!this.getCode()\n }\n\n /**\n * Get access token\n */\n async accessToken(callback?: (request: ApiRequestContract) => void): Promise<Token> {\n /**\n * We expect the user to handle errors before calling this method\n */\n if (this.hasError()) {\n throw new errors.E_OAUTH_MISSING_CODE([this.oauthTokenVerifierName])\n }\n\n /**\n * We expect the user to properly handle the state mis-match use case before\n * calling this method\n */\n if (this.stateMisMatch()) {\n throw new errors.E_OAUTH_STATE_MISMATCH()\n }\n\n /**\n * Get access token by providing the authorization code\n */\n return this.getAccessToken(\n { token: this.oauthTokenCookieValue!, secret: this.oauthSecretCookieValue! },\n (request) => {\n request.oauth1Param(this.oauthTokenVerifierName, this.getCode())\n\n if (typeof callback === 'function') {\n callback(request)\n }\n }\n )\n }\n\n /**\n * Not applicable with Oauth1\n */\n async userFromToken(): Promise<never> {\n throw new Exception(\n '\"userFromToken\" is not available with Oauth1. Use \"userFromTokenAndSecret\" instead'\n )\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
to:
|
|
3
|
-
|
|
1
|
+
{{{
|
|
2
|
+
exports({ to: app.configPath('ally.ts') })
|
|
3
|
+
}}}
|
|
4
4
|
import env from '#start/env'
|
|
5
|
-
import { defineConfig } from '@adonisjs/ally'
|
|
5
|
+
import { defineConfig, services } from '@adonisjs/ally'
|
|
6
6
|
|
|
7
7
|
const allyConfig = defineConfig({
|
|
8
8
|
{{#each providers as provider}}
|
|
9
|
-
{{provider.provider}}: {
|
|
10
|
-
driver: '{{provider.provider}}',
|
|
9
|
+
{{provider.provider}}: services.{{provider.provider}}({
|
|
11
10
|
clientId: env.get('{{provider.envPrefix}}_CLIENT_ID'),
|
|
12
11
|
clientSecret: env.get('{{provider.envPrefix}}_CLIENT_SECRET'),
|
|
13
12
|
callbackUrl: '',
|
|
14
|
-
},
|
|
13
|
+
}),
|
|
15
14
|
{{/each}}
|
|
16
15
|
})
|
|
17
16
|
|