@adonisjs/ally 5.0.0-6 → 5.0.0-8

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/README.md +5 -8
  2. package/build/chunk-CSAU5B4Q.js +10 -0
  3. package/build/chunk-CSAU5B4Q.js.map +1 -0
  4. package/build/chunk-OSVNBZ7V.js +164 -0
  5. package/build/chunk-OSVNBZ7V.js.map +1 -0
  6. package/build/chunk-UF7PETXM.js +83 -0
  7. package/build/chunk-UF7PETXM.js.map +1 -0
  8. package/build/chunk-UIZWPBWM.js +38 -0
  9. package/build/chunk-UIZWPBWM.js.map +1 -0
  10. package/build/chunk-Y3GA4Y2H.js +170 -0
  11. package/build/chunk-Y3GA4Y2H.js.map +1 -0
  12. package/build/discord-NGJGLGX7.js +136 -0
  13. package/build/discord-NGJGLGX7.js.map +1 -0
  14. package/build/facebook-WTZGLDH5.js +137 -0
  15. package/build/facebook-WTZGLDH5.js.map +1 -0
  16. package/build/github-24BPMULZ.js +173 -0
  17. package/build/github-24BPMULZ.js.map +1 -0
  18. package/build/google-NMLTQESR.js +184 -0
  19. package/build/google-NMLTQESR.js.map +1 -0
  20. package/build/index.d.ts +0 -1
  21. package/build/index.js +151 -17
  22. package/build/index.js.map +1 -0
  23. package/build/linked_in-HIRSEAEP.js +153 -0
  24. package/build/linked_in-HIRSEAEP.js.map +1 -0
  25. package/build/providers/ally_provider.js +33 -36
  26. package/build/providers/ally_provider.js.map +1 -0
  27. package/build/spotify-ESJDFUD6.js +118 -0
  28. package/build/spotify-ESJDFUD6.js.map +1 -0
  29. package/build/twitter-QISDDK24.js +101 -0
  30. package/build/twitter-QISDDK24.js.map +1 -0
  31. package/package.json +45 -33
  32. package/build/configure.js +0 -48
  33. package/build/src/abstract_drivers/oauth1.js +0 -188
  34. package/build/src/abstract_drivers/oauth2.js +0 -175
  35. package/build/src/ally_manager.js +0 -40
  36. package/build/src/debug.js +0 -10
  37. package/build/src/define_config.js +0 -75
  38. package/build/src/drivers/discord.js +0 -156
  39. package/build/src/drivers/facebook.js +0 -155
  40. package/build/src/drivers/github.js +0 -213
  41. package/build/src/drivers/google.js +0 -197
  42. package/build/src/drivers/linked_in.js +0 -166
  43. package/build/src/drivers/spotify.js +0 -130
  44. package/build/src/drivers/twitter.js +0 -117
  45. package/build/src/errors.js +0 -11
  46. package/build/src/redirect_request.js +0 -63
  47. package/build/src/types.js +0 -9
  48. package/build/stubs/main.js +0 -10
  49. /package/build/{stubs/config.stub → config/ally.stub} +0 -0
@@ -0,0 +1,136 @@
1
+ import {
2
+ Oauth2Driver
3
+ } from "./chunk-OSVNBZ7V.js";
4
+ import "./chunk-UF7PETXM.js";
5
+ import "./chunk-CSAU5B4Q.js";
6
+
7
+ // src/drivers/discord.ts
8
+ var DiscordDriver = class extends Oauth2Driver {
9
+ constructor(ctx, config) {
10
+ super(ctx, config);
11
+ this.config = config;
12
+ this.loadState();
13
+ }
14
+ accessTokenUrl = "https://discord.com/api/oauth2/token";
15
+ authorizeUrl = "https://discord.com/api/oauth2/authorize";
16
+ userInfoUrl = "https://discord.com/api/users/@me";
17
+ /**
18
+ * The param name for the authorization code
19
+ */
20
+ codeParamName = "code";
21
+ /**
22
+ * The param name for the error
23
+ */
24
+ errorParamName = "error";
25
+ /**
26
+ * Cookie name for storing the "discord_oauth_state"
27
+ */
28
+ stateCookieName = "discord_oauth_state";
29
+ /**
30
+ * Parameter name to be used for sending and receiving the state
31
+ * from Discord
32
+ */
33
+ stateParamName = "state";
34
+ /**
35
+ * Parameter name for defining the scopes
36
+ */
37
+ scopeParamName = "scope";
38
+ /**
39
+ * Scopes separator
40
+ */
41
+ scopesSeparator = " ";
42
+ /**
43
+ * Configuring the redirect request with defaults
44
+ */
45
+ configureRedirectRequest(request) {
46
+ request.scopes(this.config.scopes || ["identify", "email"]);
47
+ request.param("response_type", "code");
48
+ request.param("grant_type", "authorization_code");
49
+ if (this.config.prompt) {
50
+ request.param("prompt", this.config.prompt);
51
+ }
52
+ if (this.config.guildId) {
53
+ request.param("guild_id", this.config.guildId);
54
+ }
55
+ if (this.config.disableGuildSelect !== void 0) {
56
+ request.param("disable_guild_select", this.config.disableGuildSelect);
57
+ }
58
+ if (this.config.permissions !== void 0) {
59
+ request.param("permissions", this.config.permissions);
60
+ }
61
+ }
62
+ /**
63
+ * Configuring the access token API request to send extra fields
64
+ */
65
+ configureAccessTokenRequest(request) {
66
+ if (!this.isStateless) {
67
+ request.field("state", this.stateCookieValue);
68
+ }
69
+ }
70
+ /**
71
+ * Returns the HTTP request with the authorization header set
72
+ */
73
+ getAuthenticatedRequest(url, token) {
74
+ const request = this.httpClient(url);
75
+ request.header("Authorization", `Bearer ${token}`);
76
+ request.header("Accept", "application/json");
77
+ request.parseAs("json");
78
+ return request;
79
+ }
80
+ /**
81
+ * Fetches the user info from the Discord API
82
+ * https://discord.com/developers/docs/resources/user#get-current-user
83
+ */
84
+ async getUserInfo(token, callback) {
85
+ const request = this.getAuthenticatedRequest(this.config.userInfoUrl || this.userInfoUrl, token);
86
+ if (typeof callback === "function") {
87
+ callback(request);
88
+ }
89
+ const body = await request.get();
90
+ return {
91
+ id: body.id,
92
+ name: `${body.username}#${body.discriminator}`,
93
+ nickName: body.username,
94
+ avatarUrl: body.avatar ? `https://cdn.discordapp.com/avatars/${body.id}/${body.avatar}.${body.avatar.startsWith("a_") ? "gif" : "png"}` : `https://cdn.discordapp.com/embed/avatars/${body.discriminator % 5}.png`,
95
+ email: body.email,
96
+ // May not always be there (requires email scope)
97
+ emailVerificationState: "verified" in body ? body.verified ? "verified" : "unverified" : "unsupported",
98
+ original: body
99
+ };
100
+ }
101
+ /**
102
+ * Find if the current error code is for access denied
103
+ */
104
+ accessDenied() {
105
+ const error = this.getError();
106
+ if (!error) {
107
+ return false;
108
+ }
109
+ return error === "access_denied";
110
+ }
111
+ /**
112
+ * Returns details for the authorized user
113
+ */
114
+ async user(callback) {
115
+ const token = await this.accessToken(callback);
116
+ const user = await this.getUserInfo(token.token, callback);
117
+ return {
118
+ ...user,
119
+ token
120
+ };
121
+ }
122
+ /**
123
+ * Finds the user by the access token
124
+ */
125
+ async userFromToken(token, callback) {
126
+ const user = await this.getUserInfo(token, callback);
127
+ return {
128
+ ...user,
129
+ token: { token, type: "bearer" }
130
+ };
131
+ }
132
+ };
133
+ export {
134
+ DiscordDriver
135
+ };
136
+ //# sourceMappingURL=discord-NGJGLGX7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/drivers/discord.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 type { HttpContext } from '@adonisjs/core/http'\nimport type { HttpClient } from '@poppinss/oauth-client'\n\nimport type {\n DiscordScopes,\n DiscordToken,\n ApiRequestContract,\n DiscordDriverConfig,\n RedirectRequestContract,\n} from '../types.js'\nimport { Oauth2Driver } from '../abstract_drivers/oauth2.js'\n\n/**\n * Discord driver to login user via Discord\n */\nexport class DiscordDriver extends Oauth2Driver<DiscordToken, DiscordScopes> {\n protected accessTokenUrl = 'https://discord.com/api/oauth2/token'\n protected authorizeUrl = 'https://discord.com/api/oauth2/authorize'\n protected userInfoUrl = 'https://discord.com/api/users/@me'\n\n /**\n * The param name for the authorization code\n */\n protected codeParamName = 'code'\n\n /**\n * The param name for the error\n */\n protected errorParamName = 'error'\n\n /**\n * Cookie name for storing the \"discord_oauth_state\"\n */\n protected stateCookieName = 'discord_oauth_state'\n\n /**\n * Parameter name to be used for sending and receiving the state\n * from Discord\n */\n protected stateParamName = 'state'\n\n /**\n * Parameter name for defining the scopes\n */\n protected scopeParamName = 'scope'\n\n /**\n * Scopes separator\n */\n protected scopesSeparator = ' '\n\n constructor(\n ctx: HttpContext,\n public config: DiscordDriverConfig\n ) {\n super(ctx, config)\n\n /**\n * Extremely important to call the following method to clear the\n * state set by the redirect request\n */\n this.loadState()\n }\n\n /**\n * Configuring the redirect request with defaults\n */\n protected configureRedirectRequest(request: RedirectRequestContract<DiscordScopes>) {\n /**\n * Define user defined scopes or the default one's\n */\n request.scopes(this.config.scopes || ['identify', 'email'])\n\n request.param('response_type', 'code')\n request.param('grant_type', 'authorization_code')\n\n /**\n * Define params based upon user config\n */\n if (this.config.prompt) {\n request.param('prompt', this.config.prompt)\n }\n if (this.config.guildId) {\n request.param('guild_id', this.config.guildId)\n }\n if (this.config.disableGuildSelect !== undefined) {\n request.param('disable_guild_select', this.config.disableGuildSelect)\n }\n if (this.config.permissions !== undefined) {\n request.param('permissions', this.config.permissions)\n }\n }\n\n /**\n * Configuring the access token API request to send extra fields\n */\n protected configureAccessTokenRequest(request: ApiRequestContract) {\n /**\n * Send state to Discord when request is not stateles\n */\n if (!this.isStateless) {\n request.field('state', this.stateCookieValue)\n }\n }\n\n /**\n * Returns the HTTP request with the authorization header set\n */\n protected getAuthenticatedRequest(url: string, token: string): HttpClient {\n const request = this.httpClient(url)\n request.header('Authorization', `Bearer ${token}`)\n request.header('Accept', 'application/json')\n request.parseAs('json')\n return request\n }\n\n /**\n * Fetches the user info from the Discord API\n * https://discord.com/developers/docs/resources/user#get-current-user\n */\n protected async getUserInfo(token: string, callback?: (request: ApiRequestContract) => void) {\n const request = this.getAuthenticatedRequest(this.config.userInfoUrl || this.userInfoUrl, token)\n if (typeof callback === 'function') {\n callback(request)\n }\n\n const body = await request.get()\n return {\n id: body.id,\n name: `${body.username}#${body.discriminator}`,\n nickName: body.username,\n avatarUrl: body.avatar\n ? `https://cdn.discordapp.com/avatars/${body.id}/${body.avatar}.${\n body.avatar.startsWith('a_') ? 'gif' : 'png'\n }`\n : `https://cdn.discordapp.com/embed/avatars/${body.discriminator % 5}.png`,\n email: body.email, // May not always be there (requires email scope)\n emailVerificationState:\n 'verified' in body\n ? body.verified\n ? ('verified' as const)\n : ('unverified' as const)\n : ('unsupported' as const),\n original: body,\n }\n }\n\n /**\n * Find if the current error code is for access denied\n */\n accessDenied(): boolean {\n const error = this.getError()\n if (!error) {\n return false\n }\n\n return error === 'access_denied'\n }\n\n /**\n * Returns details for the authorized user\n */\n async user(callback?: (request: ApiRequestContract) => void) {\n const token = await this.accessToken(callback)\n const user = await this.getUserInfo(token.token, callback)\n\n return {\n ...user,\n token,\n }\n }\n\n /**\n * Finds the user by the access token\n */\n async userFromToken(token: string, callback?: (request: ApiRequestContract) => void) {\n const user = await this.getUserInfo(token, callback)\n\n return {\n ...user,\n token: { token, type: 'bearer' as const },\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,137 @@
1
+ import {
2
+ Oauth2Driver
3
+ } from "./chunk-OSVNBZ7V.js";
4
+ import "./chunk-UF7PETXM.js";
5
+ import "./chunk-CSAU5B4Q.js";
6
+
7
+ // src/drivers/facebook.ts
8
+ var FacebookDriver = class extends Oauth2Driver {
9
+ constructor(ctx, config) {
10
+ super(ctx, config);
11
+ this.config = config;
12
+ this.loadState();
13
+ }
14
+ accessTokenUrl = "https://graph.facebook.com/v10.0/oauth/access_token";
15
+ authorizeUrl = "https://www.facebook.com/v10.0/dialog/oauth";
16
+ userInfoUrl = "https://graph.facebook.com/v10.0/me";
17
+ /**
18
+ * The default set of fields to query for the user request
19
+ */
20
+ userFields = [
21
+ "name",
22
+ "first_name",
23
+ "last_name",
24
+ "link",
25
+ "email",
26
+ "picture.width(400).height(400)",
27
+ "verified"
28
+ ];
29
+ /**
30
+ * The param name for the authorization code
31
+ */
32
+ codeParamName = "code";
33
+ /**
34
+ * The param name for the error
35
+ */
36
+ errorParamName = "error";
37
+ /**
38
+ * Cookie name for storing the "facebok_oauth_state"
39
+ */
40
+ stateCookieName = "facebok_oauth_state";
41
+ /**
42
+ * Parameter name to be used for sending and receiving the state
43
+ * from Facebok
44
+ */
45
+ stateParamName = "state";
46
+ /**
47
+ * Parameter name for defining the scopes
48
+ */
49
+ scopeParamName = "scope";
50
+ /**
51
+ * Scopes separator
52
+ */
53
+ scopesSeparator = " ";
54
+ /**
55
+ * Configuring the redirect request with defaults
56
+ */
57
+ configureRedirectRequest(request) {
58
+ request.scopes(this.config.scopes || ["email"]);
59
+ request.param("response_type", "code");
60
+ request.param("grant_type", "authorization_code");
61
+ if (this.config.display) {
62
+ request.param("display", this.config.display);
63
+ }
64
+ if (this.config.authType) {
65
+ request.param("auth_type", this.config.authType);
66
+ }
67
+ }
68
+ /**
69
+ * Returns the HTTP request with the authorization header set
70
+ */
71
+ getAuthenticatedRequest(url, token) {
72
+ const request = this.httpClient(url);
73
+ request.header("Authorization", `Bearer ${token}`);
74
+ request.header("Accept", "application/json");
75
+ request.parseAs("json");
76
+ return request;
77
+ }
78
+ /**
79
+ * Fetches the user info from the Facebook API
80
+ * https://developers.facebook.com/docs/graph-api/reference/user/
81
+ */
82
+ async getUserInfo(token, callback) {
83
+ const request = this.getAuthenticatedRequest(this.config.userInfoUrl || this.userInfoUrl, token);
84
+ request.param("fields", (this.config.userFields || this.userFields).join(","));
85
+ const body = await request.get();
86
+ if (typeof callback === "function") {
87
+ callback(request);
88
+ }
89
+ return {
90
+ id: body.id,
91
+ name: body.name,
92
+ nickName: body.name,
93
+ // https://developers.facebook.com/docs/graph-api/reference/user/picture/
94
+ avatarUrl: body.picture?.data?.url || null,
95
+ email: body.email || null,
96
+ // May not always be there (requires email scope)
97
+ // Important note: https://developers.facebook.com/docs/facebook-login/multiple-providers#postfb1
98
+ emailVerificationState: "verified" in body ? body.verified ? "verified" : "unverified" : "unsupported",
99
+ original: body
100
+ };
101
+ }
102
+ /**
103
+ * Find if the current error code is for access denied
104
+ */
105
+ accessDenied() {
106
+ const error = this.getError();
107
+ if (!error) {
108
+ return false;
109
+ }
110
+ return error === "access_denied";
111
+ }
112
+ /**
113
+ * Returns details for the authorized user
114
+ */
115
+ async user(callback) {
116
+ const token = await this.accessToken(callback);
117
+ const user = await this.getUserInfo(token.token, callback);
118
+ return {
119
+ ...user,
120
+ token
121
+ };
122
+ }
123
+ /**
124
+ * Finds the user by the access token
125
+ */
126
+ async userFromToken(token, callback) {
127
+ const user = await this.getUserInfo(token, callback);
128
+ return {
129
+ ...user,
130
+ token: { token, type: "bearer" }
131
+ };
132
+ }
133
+ };
134
+ export {
135
+ FacebookDriver
136
+ };
137
+ //# sourceMappingURL=facebook-WTZGLDH5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/drivers/facebook.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 type { HttpClient } from '@poppinss/oauth-client'\nimport type { HttpContext } from '@adonisjs/core/http'\nimport type {\n FacebookToken,\n FacebookScopes,\n LiteralStringUnion,\n ApiRequestContract,\n FacebookDriverConfig,\n FacebookProfileFields,\n RedirectRequestContract,\n} from '../types.js'\nimport { Oauth2Driver } from '../abstract_drivers/oauth2.js'\n\n/**\n * Facebook driver to login user via Facebook\n */\nexport class FacebookDriver extends Oauth2Driver<FacebookToken, FacebookScopes> {\n protected accessTokenUrl = 'https://graph.facebook.com/v10.0/oauth/access_token'\n protected authorizeUrl = 'https://www.facebook.com/v10.0/dialog/oauth'\n protected userInfoUrl = 'https://graph.facebook.com/v10.0/me'\n\n /**\n * The default set of fields to query for the user request\n */\n protected userFields: LiteralStringUnion<FacebookProfileFields>[] = [\n 'name',\n 'first_name',\n 'last_name',\n 'link',\n 'email',\n 'picture.width(400).height(400)',\n 'verified',\n ]\n\n /**\n * The param name for the authorization code\n */\n protected codeParamName = 'code'\n\n /**\n * The param name for the error\n */\n protected errorParamName = 'error'\n\n /**\n * Cookie name for storing the \"facebok_oauth_state\"\n */\n protected stateCookieName = 'facebok_oauth_state'\n\n /**\n * Parameter name to be used for sending and receiving the state\n * from Facebok\n */\n protected stateParamName = 'state'\n\n /**\n * Parameter name for defining the scopes\n */\n protected scopeParamName = 'scope'\n\n /**\n * Scopes separator\n */\n protected scopesSeparator = ' '\n\n constructor(\n ctx: HttpContext,\n public config: FacebookDriverConfig\n ) {\n super(ctx, config)\n\n /**\n * Extremely important to call the following method to clear the\n * state set by the redirect request\n */\n this.loadState()\n }\n\n /**\n * Configuring the redirect request with defaults\n */\n protected configureRedirectRequest(request: RedirectRequestContract<FacebookScopes>) {\n /**\n * Define user defined scopes or the default one's\n */\n request.scopes(this.config.scopes || ['email'])\n\n request.param('response_type', 'code')\n request.param('grant_type', 'authorization_code')\n\n /**\n * Define params based upon user config\n */\n if (this.config.display) {\n request.param('display', this.config.display)\n }\n if (this.config.authType) {\n request.param('auth_type', this.config.authType)\n }\n }\n\n /**\n * Returns the HTTP request with the authorization header set\n */\n protected getAuthenticatedRequest(url: string, token: string): HttpClient {\n const request = this.httpClient(url)\n request.header('Authorization', `Bearer ${token}`)\n request.header('Accept', 'application/json')\n request.parseAs('json')\n return request\n }\n\n /**\n * Fetches the user info from the Facebook API\n * https://developers.facebook.com/docs/graph-api/reference/user/\n */\n protected async getUserInfo(token: string, callback?: (request: ApiRequestContract) => void) {\n const request = this.getAuthenticatedRequest(this.config.userInfoUrl || this.userInfoUrl, token)\n request.param('fields', (this.config.userFields || this.userFields).join(','))\n\n const body = await request.get()\n\n /**\n * Invoke callback if defined\n */\n if (typeof callback === 'function') {\n callback(request)\n }\n\n return {\n id: body.id,\n name: body.name,\n nickName: body.name,\n // https://developers.facebook.com/docs/graph-api/reference/user/picture/\n avatarUrl: body.picture?.data?.url || null,\n email: body.email || null, // May not always be there (requires email scope)\n // Important note: https://developers.facebook.com/docs/facebook-login/multiple-providers#postfb1\n emailVerificationState:\n 'verified' in body\n ? body.verified\n ? ('verified' as const)\n : ('unverified' as const)\n : ('unsupported' as const),\n original: body,\n }\n }\n\n /**\n * Find if the current error code is for access denied\n */\n accessDenied(): boolean {\n const error = this.getError()\n if (!error) {\n return false\n }\n\n return error === 'access_denied'\n }\n\n /**\n * Returns details for the authorized user\n */\n async user(callback?: (request: ApiRequestContract) => void) {\n const token = await this.accessToken(callback)\n const user = await this.getUserInfo(token.token, callback)\n\n return {\n ...user,\n token,\n }\n }\n\n /**\n * Finds the user by the access token\n */\n async userFromToken(token: string, callback?: (request: ApiRequestContract) => void) {\n const user = await this.getUserInfo(token, callback)\n\n return {\n ...user,\n token: { token, type: 'bearer' as const },\n }\n }\n}\n"],"mappings":";;;;;;;AAyBO,IAAM,iBAAN,cAA6B,aAA4C;AAAA,EAiD9E,YACE,KACO,QACP;AACA,UAAM,KAAK,MAAM;AAFV;AAQP,SAAK,UAAU;AAAA,EACjB;AAAA,EA3DU,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,cAAc;AAAA;AAAA;AAAA;AAAA,EAKd,aAA0D;AAAA,IAClE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKU,gBAAgB;AAAA;AAAA;AAAA;AAAA,EAKhB,iBAAiB;AAAA;AAAA;AAAA;AAAA,EAKjB,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMlB,iBAAiB;AAAA;AAAA;AAAA;AAAA,EAKjB,iBAAiB;AAAA;AAAA;AAAA;AAAA,EAKjB,kBAAkB;AAAA;AAAA;AAAA;AAAA,EAkBlB,yBAAyB,SAAkD;AAInF,YAAQ,OAAO,KAAK,OAAO,UAAU,CAAC,OAAO,CAAC;AAE9C,YAAQ,MAAM,iBAAiB,MAAM;AACrC,YAAQ,MAAM,cAAc,oBAAoB;AAKhD,QAAI,KAAK,OAAO,SAAS;AACvB,cAAQ,MAAM,WAAW,KAAK,OAAO,OAAO;AAAA,IAC9C;AACA,QAAI,KAAK,OAAO,UAAU;AACxB,cAAQ,MAAM,aAAa,KAAK,OAAO,QAAQ;AAAA,IACjD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKU,wBAAwB,KAAa,OAA2B;AACxE,UAAM,UAAU,KAAK,WAAW,GAAG;AACnC,YAAQ,OAAO,iBAAiB,UAAU,KAAK,EAAE;AACjD,YAAQ,OAAO,UAAU,kBAAkB;AAC3C,YAAQ,QAAQ,MAAM;AACtB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAgB,YAAY,OAAe,UAAkD;AAC3F,UAAM,UAAU,KAAK,wBAAwB,KAAK,OAAO,eAAe,KAAK,aAAa,KAAK;AAC/F,YAAQ,MAAM,WAAW,KAAK,OAAO,cAAc,KAAK,YAAY,KAAK,GAAG,CAAC;AAE7E,UAAM,OAAO,MAAM,QAAQ,IAAI;AAK/B,QAAI,OAAO,aAAa,YAAY;AAClC,eAAS,OAAO;AAAA,IAClB;AAEA,WAAO;AAAA,MACL,IAAI,KAAK;AAAA,MACT,MAAM,KAAK;AAAA,MACX,UAAU,KAAK;AAAA;AAAA,MAEf,WAAW,KAAK,SAAS,MAAM,OAAO;AAAA,MACtC,OAAO,KAAK,SAAS;AAAA;AAAA;AAAA,MAErB,wBACE,cAAc,OACV,KAAK,WACF,aACA,eACF;AAAA,MACP,UAAU;AAAA,IACZ;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,eAAwB;AACtB,UAAM,QAAQ,KAAK,SAAS;AAC5B,QAAI,CAAC,OAAO;AACV,aAAO;AAAA,IACT;AAEA,WAAO,UAAU;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAK,UAAkD;AAC3D,UAAM,QAAQ,MAAM,KAAK,YAAY,QAAQ;AAC7C,UAAM,OAAO,MAAM,KAAK,YAAY,MAAM,OAAO,QAAQ;AAEzD,WAAO;AAAA,MACL,GAAG;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,OAAe,UAAkD;AACnF,UAAM,OAAO,MAAM,KAAK,YAAY,OAAO,QAAQ;AAEnD,WAAO;AAAA,MACL,GAAG;AAAA,MACH,OAAO,EAAE,OAAO,MAAM,SAAkB;AAAA,IAC1C;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,173 @@
1
+ import {
2
+ Oauth2Driver
3
+ } from "./chunk-OSVNBZ7V.js";
4
+ import "./chunk-UF7PETXM.js";
5
+ import "./chunk-CSAU5B4Q.js";
6
+
7
+ // src/drivers/github.ts
8
+ var GithubDriver = class extends Oauth2Driver {
9
+ constructor(ctx, config) {
10
+ super(ctx, config);
11
+ this.config = config;
12
+ this.loadState();
13
+ }
14
+ accessTokenUrl = "https://github.com/login/oauth/access_token";
15
+ authorizeUrl = "https://github.com/login/oauth/authorize";
16
+ userInfoUrl = "https://api.github.com/user";
17
+ userEmailUrl = "https://api.github.com/user/emails";
18
+ /**
19
+ * The param name for the authorization code
20
+ */
21
+ codeParamName = "code";
22
+ /**
23
+ * The param name for the error
24
+ */
25
+ errorParamName = "error";
26
+ /**
27
+ * Cookie name for storing the "gh_oauth_state"
28
+ */
29
+ stateCookieName = "gh_oauth_state";
30
+ /**
31
+ * Parameter name to be used for sending and receiving the state
32
+ * from Github
33
+ */
34
+ stateParamName = "state";
35
+ /**
36
+ * Parameter name for defining the scopes
37
+ */
38
+ scopeParamName = "scope";
39
+ /**
40
+ * Scopes separator
41
+ */
42
+ scopesSeparator = " ";
43
+ /**
44
+ * Configuring the redirect request with defaults
45
+ */
46
+ configureRedirectRequest(request) {
47
+ request.scopes(this.config.scopes || ["user"]);
48
+ if (this.config.allowSignup !== void 0) {
49
+ request.param("allow_signup", this.config.allowSignup);
50
+ }
51
+ if (this.config.login) {
52
+ request.param("login", this.config.login);
53
+ }
54
+ }
55
+ /**
56
+ * Configuring the access token API request to send extra fields
57
+ */
58
+ configureAccessTokenRequest(request) {
59
+ if (!this.isStateless) {
60
+ request.field("state", this.stateCookieValue);
61
+ }
62
+ request.clearField("grant_type");
63
+ }
64
+ /**
65
+ * Returns the HTTP request with the authorization header set
66
+ */
67
+ getAuthenticatedRequest(url, token) {
68
+ const request = this.httpClient(url);
69
+ request.header("Authorization", `token ${token}`);
70
+ request.header("Accept", "application/json");
71
+ request.parseAs("json");
72
+ return request;
73
+ }
74
+ /**
75
+ * Fetches the user info from the Github API
76
+ * https://docs.github.com/en/rest/reference/users#get-the-authenticated-user
77
+ */
78
+ async getUserInfo(token, callback) {
79
+ const request = this.getAuthenticatedRequest(this.config.userInfoUrl || this.userInfoUrl, token);
80
+ if (typeof callback === "function") {
81
+ callback(request);
82
+ }
83
+ const body = await request.get();
84
+ return {
85
+ id: body.id,
86
+ nickName: body.name,
87
+ email: body.email,
88
+ // May not always be there
89
+ emailVerificationState: body.email ? "verified" : "unsupported",
90
+ name: body.name,
91
+ avatarUrl: body.avatar_url,
92
+ original: body
93
+ };
94
+ }
95
+ /**
96
+ * Fetches the user email from the Github API.
97
+ * https://docs.github.com/en/rest/reference/users#list-email-addresses-for-the-authenticated-user
98
+ */
99
+ async getUserEmail(token, callback) {
100
+ const request = this.getAuthenticatedRequest(
101
+ this.config.userEmailUrl || this.userEmailUrl,
102
+ token
103
+ );
104
+ if (typeof callback === "function") {
105
+ callback(request);
106
+ }
107
+ try {
108
+ let emails = await request.get();
109
+ emails = emails.sort((email) => email.primary ? -1 : 1);
110
+ let mainEmail = emails.find((email) => email.verified);
111
+ if (!mainEmail) {
112
+ mainEmail = emails[0];
113
+ }
114
+ return mainEmail;
115
+ } catch (error) {
116
+ if (error && error.response && error.response.statusCode === 404) {
117
+ return;
118
+ }
119
+ throw error;
120
+ }
121
+ }
122
+ /**
123
+ * Find if the current error code is for access denied
124
+ */
125
+ accessDenied() {
126
+ const error = this.getError();
127
+ if (!error) {
128
+ return false;
129
+ }
130
+ return error === "access_denied";
131
+ }
132
+ /**
133
+ * Returns details for the authorized user
134
+ */
135
+ async user(callback) {
136
+ const token = await this.accessToken(callback);
137
+ const user = await this.getUserInfo(token.token, callback);
138
+ if (!user.email) {
139
+ this.ctx.logger.trace("Fetching github user email separately");
140
+ const emailResponse = await this.getUserEmail(token.token, callback);
141
+ if (emailResponse) {
142
+ user.email = emailResponse.email;
143
+ user.emailVerificationState = emailResponse.verified ? "verified" : "unverified";
144
+ }
145
+ }
146
+ return {
147
+ ...user,
148
+ token
149
+ };
150
+ }
151
+ /**
152
+ * Finds the user by the access token
153
+ */
154
+ async userFromToken(token, callback) {
155
+ const user = await this.getUserInfo(token, callback);
156
+ if (!user.email) {
157
+ this.ctx.logger.trace("Fetching github user email separately");
158
+ const emailResponse = await this.getUserEmail(token, callback);
159
+ if (emailResponse) {
160
+ user.email = emailResponse.email;
161
+ user.emailVerificationState = emailResponse.verified ? "verified" : "unverified";
162
+ }
163
+ }
164
+ return {
165
+ ...user,
166
+ token: { token, type: "bearer" }
167
+ };
168
+ }
169
+ };
170
+ export {
171
+ GithubDriver
172
+ };
173
+ //# sourceMappingURL=github-24BPMULZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/drivers/github.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 type { HttpContext } from '@adonisjs/core/http'\nimport type { HttpClient } from '@poppinss/oauth-client'\nimport type {\n GithubToken,\n GithubScopes,\n AllyUserContract,\n GithubDriverConfig,\n ApiRequestContract,\n RedirectRequestContract,\n} from '../types.js'\nimport { Oauth2Driver } from '../abstract_drivers/oauth2.js'\n\n/**\n * Github driver to login user via Github\n */\nexport class GithubDriver extends Oauth2Driver<GithubToken, GithubScopes> {\n protected accessTokenUrl = 'https://github.com/login/oauth/access_token'\n protected authorizeUrl = 'https://github.com/login/oauth/authorize'\n protected userInfoUrl = 'https://api.github.com/user'\n protected userEmailUrl = 'https://api.github.com/user/emails'\n\n /**\n * The param name for the authorization code\n */\n protected codeParamName = 'code'\n\n /**\n * The param name for the error\n */\n protected errorParamName = 'error'\n\n /**\n * Cookie name for storing the \"gh_oauth_state\"\n */\n protected stateCookieName = 'gh_oauth_state'\n\n /**\n * Parameter name to be used for sending and receiving the state\n * from Github\n */\n protected stateParamName = 'state'\n\n /**\n * Parameter name for defining the scopes\n */\n protected scopeParamName = 'scope'\n\n /**\n * Scopes separator\n */\n protected scopesSeparator = ' '\n\n constructor(\n ctx: HttpContext,\n public config: GithubDriverConfig\n ) {\n super(ctx, config)\n /**\n * Extremely important to call the following method to clear the\n * state set by the redirect request\n */\n this.loadState()\n }\n\n /**\n * Configuring the redirect request with defaults\n */\n protected configureRedirectRequest(request: RedirectRequestContract<GithubScopes>) {\n /**\n * Define user defined scopes or the default one's\n */\n request.scopes(this.config.scopes || ['user'])\n\n /**\n * Set \"allow_signup\" option when defined\n */\n if (this.config.allowSignup !== undefined) {\n request.param('allow_signup', this.config.allowSignup)\n }\n\n /**\n * Set \"login\" option when defined\n */\n if (this.config.login) {\n request.param('login', this.config.login)\n }\n }\n\n /**\n * Configuring the access token API request to send extra fields\n */\n protected configureAccessTokenRequest(request: ApiRequestContract) {\n /**\n * Send state to github when request is not stateles\n */\n if (!this.isStateless) {\n request.field('state', this.stateCookieValue)\n }\n\n /**\n * Clearing the default defined \"grant_type\". Github doesn't accept this.\n * https://github.com/poppinss/oauth-client#following-is-the-list-of-fieldsparams-set-by-the-clients-implicitly\n */\n request.clearField('grant_type')\n }\n\n /**\n * Returns the HTTP request with the authorization header set\n */\n protected getAuthenticatedRequest(url: string, token: string): HttpClient {\n const request = this.httpClient(url)\n request.header('Authorization', `token ${token}`)\n request.header('Accept', 'application/json')\n request.parseAs('json')\n return request\n }\n\n /**\n * Fetches the user info from the Github API\n * https://docs.github.com/en/rest/reference/users#get-the-authenticated-user\n */\n protected async getUserInfo(token: string, callback?: (request: ApiRequestContract) => void) {\n const request = this.getAuthenticatedRequest(this.config.userInfoUrl || this.userInfoUrl, token)\n if (typeof callback === 'function') {\n callback(request)\n }\n\n const body = await request.get()\n return {\n id: body.id,\n nickName: body.name,\n email: body.email, // May not always be there\n emailVerificationState: (body.email\n ? 'verified'\n : 'unsupported') as AllyUserContract<any>['emailVerificationState'],\n name: body.name,\n avatarUrl: body.avatar_url,\n original: body,\n }\n }\n\n /**\n * Fetches the user email from the Github API.\n * https://docs.github.com/en/rest/reference/users#list-email-addresses-for-the-authenticated-user\n */\n protected async getUserEmail(token: string, callback?: (request: ApiRequestContract) => void) {\n const request = this.getAuthenticatedRequest(\n this.config.userEmailUrl || this.userEmailUrl,\n token\n )\n\n if (typeof callback === 'function') {\n callback(request)\n }\n\n try {\n let emails = await request.get()\n\n /**\n * Sort emails to keep the primary ones on the top\n */\n emails = emails.sort((email: any) => (email.primary ? -1 : 1))\n\n /**\n * Get the first verified email of the user\n */\n let mainEmail = emails.find((email: any) => email.verified)\n\n /**\n * If there are no verified emails, then get any first one\n */\n if (!mainEmail) {\n mainEmail = emails[0]\n }\n\n return mainEmail\n } catch (error) {\n if (error && error.response && error.response.statusCode === 404) {\n return\n }\n throw error\n }\n }\n\n /**\n * Find if the current error code is for access denied\n */\n accessDenied(): boolean {\n const error = this.getError()\n if (!error) {\n return false\n }\n\n return error === 'access_denied'\n }\n\n /**\n * Returns details for the authorized user\n */\n async user(callback?: (request: ApiRequestContract) => void) {\n const token = await this.accessToken(callback)\n const user = await this.getUserInfo(token.token, callback)\n\n /**\n * Fetch email separately\n */\n if (!user.email) {\n this.ctx.logger.trace('Fetching github user email separately')\n\n const emailResponse = await this.getUserEmail(token.token, callback)\n if (emailResponse) {\n user.email = emailResponse.email\n user.emailVerificationState = emailResponse.verified\n ? ('verified' as const)\n : ('unverified' as const)\n }\n }\n\n return {\n ...user,\n token: token,\n }\n }\n\n /**\n * Finds the user by the access token\n */\n async userFromToken(token: string, callback?: (request: ApiRequestContract) => void) {\n const user = await this.getUserInfo(token, callback)\n\n /**\n * Fetch email separately\n */\n if (!user.email) {\n this.ctx.logger.trace('Fetching github user email separately')\n\n const emailResponse = await this.getUserEmail(token, callback)\n if (emailResponse) {\n user.email = emailResponse.email\n user.emailVerificationState = emailResponse.verified\n ? ('verified' as const)\n : ('unverified' as const)\n }\n }\n\n return {\n ...user,\n token: { token, type: 'bearer' as const },\n }\n }\n}\n"],"mappings":";;;;;;;AAwBO,IAAM,eAAN,cAA2B,aAAwC;AAAA,EAqCxE,YACE,KACO,QACP;AACA,UAAM,KAAK,MAAM;AAFV;AAOP,SAAK,UAAU;AAAA,EACjB;AAAA,EA9CU,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,cAAc;AAAA,EACd,eAAe;AAAA;AAAA;AAAA;AAAA,EAKf,gBAAgB;AAAA;AAAA;AAAA;AAAA,EAKhB,iBAAiB;AAAA;AAAA;AAAA;AAAA,EAKjB,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMlB,iBAAiB;AAAA;AAAA;AAAA;AAAA,EAKjB,iBAAiB;AAAA;AAAA;AAAA;AAAA,EAKjB,kBAAkB;AAAA;AAAA;AAAA;AAAA,EAiBlB,yBAAyB,SAAgD;AAIjF,YAAQ,OAAO,KAAK,OAAO,UAAU,CAAC,MAAM,CAAC;AAK7C,QAAI,KAAK,OAAO,gBAAgB,QAAW;AACzC,cAAQ,MAAM,gBAAgB,KAAK,OAAO,WAAW;AAAA,IACvD;AAKA,QAAI,KAAK,OAAO,OAAO;AACrB,cAAQ,MAAM,SAAS,KAAK,OAAO,KAAK;AAAA,IAC1C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKU,4BAA4B,SAA6B;AAIjE,QAAI,CAAC,KAAK,aAAa;AACrB,cAAQ,MAAM,SAAS,KAAK,gBAAgB;AAAA,IAC9C;AAMA,YAAQ,WAAW,YAAY;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKU,wBAAwB,KAAa,OAA2B;AACxE,UAAM,UAAU,KAAK,WAAW,GAAG;AACnC,YAAQ,OAAO,iBAAiB,SAAS,KAAK,EAAE;AAChD,YAAQ,OAAO,UAAU,kBAAkB;AAC3C,YAAQ,QAAQ,MAAM;AACtB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAgB,YAAY,OAAe,UAAkD;AAC3F,UAAM,UAAU,KAAK,wBAAwB,KAAK,OAAO,eAAe,KAAK,aAAa,KAAK;AAC/F,QAAI,OAAO,aAAa,YAAY;AAClC,eAAS,OAAO;AAAA,IAClB;AAEA,UAAM,OAAO,MAAM,QAAQ,IAAI;AAC/B,WAAO;AAAA,MACL,IAAI,KAAK;AAAA,MACT,UAAU,KAAK;AAAA,MACf,OAAO,KAAK;AAAA;AAAA,MACZ,wBAAyB,KAAK,QAC1B,aACA;AAAA,MACJ,MAAM,KAAK;AAAA,MACX,WAAW,KAAK;AAAA,MAChB,UAAU;AAAA,IACZ;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAgB,aAAa,OAAe,UAAkD;AAC5F,UAAM,UAAU,KAAK;AAAA,MACnB,KAAK,OAAO,gBAAgB,KAAK;AAAA,MACjC;AAAA,IACF;AAEA,QAAI,OAAO,aAAa,YAAY;AAClC,eAAS,OAAO;AAAA,IAClB;AAEA,QAAI;AACF,UAAI,SAAS,MAAM,QAAQ,IAAI;AAK/B,eAAS,OAAO,KAAK,CAAC,UAAgB,MAAM,UAAU,KAAK,CAAE;AAK7D,UAAI,YAAY,OAAO,KAAK,CAAC,UAAe,MAAM,QAAQ;AAK1D,UAAI,CAAC,WAAW;AACd,oBAAY,OAAO,CAAC;AAAA,MACtB;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI,SAAS,MAAM,YAAY,MAAM,SAAS,eAAe,KAAK;AAChE;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,eAAwB;AACtB,UAAM,QAAQ,KAAK,SAAS;AAC5B,QAAI,CAAC,OAAO;AACV,aAAO;AAAA,IACT;AAEA,WAAO,UAAU;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAK,UAAkD;AAC3D,UAAM,QAAQ,MAAM,KAAK,YAAY,QAAQ;AAC7C,UAAM,OAAO,MAAM,KAAK,YAAY,MAAM,OAAO,QAAQ;AAKzD,QAAI,CAAC,KAAK,OAAO;AACf,WAAK,IAAI,OAAO,MAAM,uCAAuC;AAE7D,YAAM,gBAAgB,MAAM,KAAK,aAAa,MAAM,OAAO,QAAQ;AACnE,UAAI,eAAe;AACjB,aAAK,QAAQ,cAAc;AAC3B,aAAK,yBAAyB,cAAc,WACvC,aACA;AAAA,MACP;AAAA,IACF;AAEA,WAAO;AAAA,MACL,GAAG;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,OAAe,UAAkD;AACnF,UAAM,OAAO,MAAM,KAAK,YAAY,OAAO,QAAQ;AAKnD,QAAI,CAAC,KAAK,OAAO;AACf,WAAK,IAAI,OAAO,MAAM,uCAAuC;AAE7D,YAAM,gBAAgB,MAAM,KAAK,aAAa,OAAO,QAAQ;AAC7D,UAAI,eAAe;AACjB,aAAK,QAAQ,cAAc;AAC3B,aAAK,yBAAyB,cAAc,WACvC,aACA;AAAA,MACP;AAAA,IACF;AAEA,WAAO;AAAA,MACL,GAAG;AAAA,MACH,OAAO,EAAE,OAAO,MAAM,SAAkB;AAAA,IAC1C;AAAA,EACF;AACF;","names":[]}