@atlasauth/js 0.16.0 → 0.18.0
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/CHANGELOG.md +19 -0
- package/dist/better-auth-bridge.d.ts +62 -0
- package/dist/better-auth-bridge.js +83 -0
- package/dist/better-auth-bridge.js.map +1 -0
- package/dist/captcha-controller.js +1 -1
- package/dist/captcha-controller.js.map +1 -1
- package/dist/captcha-widget.d.ts +20 -2
- package/dist/captcha-widget.js +79 -4
- package/dist/captcha-widget.js.map +1 -1
- package/dist/captcha.d.ts +5 -0
- package/dist/captcha.js +30 -0
- package/dist/captcha.js.map +1 -1
- package/dist/compat.d.ts +149 -0
- package/dist/compat.js +363 -0
- package/dist/compat.js.map +1 -0
- package/dist/device-authorization.d.ts +70 -0
- package/dist/device-authorization.js +97 -0
- package/dist/device-authorization.js.map +1 -0
- package/dist/email-code-check.d.ts +60 -0
- package/dist/email-code-check.js +51 -0
- package/dist/email-code-check.js.map +1 -0
- package/dist/frontchannel-logout.d.ts +36 -0
- package/dist/frontchannel-logout.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/passkey-sign-up.d.ts +2 -2
- package/dist/passkey-sign-up.js +7 -1
- package/dist/passkey-sign-up.js.map +1 -1
- package/dist/passkey.d.ts +58 -2
- package/dist/passkey.js +61 -0
- package/dist/passkey.js.map +1 -1
- package/dist/sign-out-guard.d.ts +7 -0
- package/dist/sign-out-guard.js +38 -4
- package/dist/sign-out-guard.js.map +1 -1
- package/dist/sign-out.d.ts +23 -0
- package/dist/sign-out.js +37 -2
- package/dist/sign-out.js.map +1 -1
- package/dist/upstream-logout.d.ts +26 -0
- package/dist/upstream-logout.js +60 -0
- package/dist/upstream-logout.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +12 -1
package/dist/compat.d.ts
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
export interface Auth0CompatClientOptions {
|
|
2
|
+
/** The instance publishable key. `clientId` is accepted as an alias. */
|
|
3
|
+
publishableKey?: string;
|
|
4
|
+
/** The instance's Frontend API origin (`https://auth.example.com`). `domain` is accepted as an alias. */
|
|
5
|
+
frontendApi?: string;
|
|
6
|
+
/** auth0-spa-js names, accepted so existing option objects keep working. */
|
|
7
|
+
clientId?: string;
|
|
8
|
+
domain?: string;
|
|
9
|
+
authorizationParams?: {
|
|
10
|
+
redirect_uri?: string;
|
|
11
|
+
[key: string]: unknown;
|
|
12
|
+
};
|
|
13
|
+
/** Where sign-in happens (default: the instance's hosted page, `<frontendApi>/hosted/sign-in`). */
|
|
14
|
+
signInUrl?: string;
|
|
15
|
+
/** Where sign-up happens (default `<frontendApi>/hosted/sign-up`), used for `screen_hint: 'signup'`. */
|
|
16
|
+
signUpUrl?: string;
|
|
17
|
+
fetchImpl?: typeof fetch;
|
|
18
|
+
[option: string]: unknown;
|
|
19
|
+
}
|
|
20
|
+
/** The OIDC-profile user auth0-spa-js's `getUser()` returns. */
|
|
21
|
+
export interface Auth0CompatUser {
|
|
22
|
+
sub: string;
|
|
23
|
+
name?: string;
|
|
24
|
+
given_name?: string;
|
|
25
|
+
family_name?: string;
|
|
26
|
+
nickname?: string;
|
|
27
|
+
picture?: string;
|
|
28
|
+
email?: string;
|
|
29
|
+
email_verified?: boolean;
|
|
30
|
+
[claim: string]: unknown;
|
|
31
|
+
}
|
|
32
|
+
export interface Auth0CompatRedirectOptions {
|
|
33
|
+
appState?: unknown;
|
|
34
|
+
authorizationParams?: {
|
|
35
|
+
/** A social provider to go straight to (`github`, `google-oauth2`, …). */
|
|
36
|
+
connection?: string;
|
|
37
|
+
redirect_uri?: string;
|
|
38
|
+
/** `signup` opens the sign-up page. */
|
|
39
|
+
screen_hint?: string;
|
|
40
|
+
[key: string]: unknown;
|
|
41
|
+
};
|
|
42
|
+
/** Called with the URL instead of navigating (auth0-spa-js `openUrl`). */
|
|
43
|
+
openUrl?: (url: string) => void | Promise<void>;
|
|
44
|
+
}
|
|
45
|
+
export interface Auth0CompatLogoutOptions {
|
|
46
|
+
logoutParams?: {
|
|
47
|
+
returnTo?: string;
|
|
48
|
+
[key: string]: unknown;
|
|
49
|
+
};
|
|
50
|
+
/** `false` signs out without navigating; a function receives the URL instead. */
|
|
51
|
+
openUrl?: false | ((url: string) => void | Promise<void>);
|
|
52
|
+
}
|
|
53
|
+
export interface Auth0CompatTokenOptions {
|
|
54
|
+
/** `'off'` always mints a fresh token. */
|
|
55
|
+
cacheMode?: 'on' | 'off' | 'cache-only';
|
|
56
|
+
/** Resolve `{ access_token, id_token, expires_in }` instead of the token string. */
|
|
57
|
+
detailedResponse?: boolean;
|
|
58
|
+
/** An Atlas JWT template name, for a named-template token. */
|
|
59
|
+
template?: string;
|
|
60
|
+
authorizationParams?: Record<string, unknown>;
|
|
61
|
+
}
|
|
62
|
+
/** auth0-spa-js-style errors: `error` carries the OAuth-ish code apps branch on. */
|
|
63
|
+
export declare class Auth0CompatError extends Error {
|
|
64
|
+
readonly error: 'login_required' | 'popup_closed' | 'popup_blocked' | 'timeout' | 'missing_transaction' | 'start_failed';
|
|
65
|
+
constructor(error: 'login_required' | 'popup_closed' | 'popup_blocked' | 'timeout' | 'missing_transaction' | 'start_failed', message: string);
|
|
66
|
+
}
|
|
67
|
+
interface AtlasClientBody {
|
|
68
|
+
session: {
|
|
69
|
+
id: string;
|
|
70
|
+
} | null;
|
|
71
|
+
user: {
|
|
72
|
+
id: string;
|
|
73
|
+
first_name: string | null;
|
|
74
|
+
last_name: string | null;
|
|
75
|
+
username: string | null;
|
|
76
|
+
image_url: string | null;
|
|
77
|
+
email_addresses?: Array<{
|
|
78
|
+
email_address: string;
|
|
79
|
+
verified: boolean;
|
|
80
|
+
primary: boolean;
|
|
81
|
+
}>;
|
|
82
|
+
} | null;
|
|
83
|
+
jwt?: string;
|
|
84
|
+
}
|
|
85
|
+
/** Decode a JWT's payload (no verification: it came from our own FAPI). */
|
|
86
|
+
export declare function decodeJwtPayload(jwt: string): Record<string, unknown> | null;
|
|
87
|
+
/** Project the Frontend API user onto the OIDC profile shape. */
|
|
88
|
+
export declare function auth0UserFromClient(user: AtlasClientBody['user']): Auth0CompatUser | undefined;
|
|
89
|
+
/** The auth0-spa-js `Auth0Client`, on Atlas. */
|
|
90
|
+
export declare class Auth0CompatClient {
|
|
91
|
+
readonly publishableKey: string;
|
|
92
|
+
readonly frontendApi: string;
|
|
93
|
+
private readonly fapi;
|
|
94
|
+
private readonly raw;
|
|
95
|
+
private readonly options;
|
|
96
|
+
private state;
|
|
97
|
+
private token;
|
|
98
|
+
constructor(options: Auth0CompatClientOptions);
|
|
99
|
+
private signInUrl;
|
|
100
|
+
/** Read the Frontend API client state (session, user, token). */
|
|
101
|
+
private load;
|
|
102
|
+
private keepToken;
|
|
103
|
+
/** `checkSession()`: refresh the local view of the session; never throws. */
|
|
104
|
+
checkSession(): Promise<void>;
|
|
105
|
+
isAuthenticated(): Promise<boolean>;
|
|
106
|
+
getUser<TUser extends Auth0CompatUser = Auth0CompatUser>(): Promise<TUser | undefined>;
|
|
107
|
+
getIdTokenClaims(): Promise<(Record<string, unknown> & {
|
|
108
|
+
__raw: string;
|
|
109
|
+
}) | undefined>;
|
|
110
|
+
/** The Atlas session token (or a named-template token), refreshed when close to expiry. */
|
|
111
|
+
getTokenSilently(options: Auth0CompatTokenOptions & {
|
|
112
|
+
detailedResponse: true;
|
|
113
|
+
}): Promise<{
|
|
114
|
+
access_token: string;
|
|
115
|
+
id_token: string;
|
|
116
|
+
expires_in: number;
|
|
117
|
+
}>;
|
|
118
|
+
getTokenSilently(options?: Auth0CompatTokenOptions): Promise<string>;
|
|
119
|
+
/** Sign in in a popup when needed, then return a token. */
|
|
120
|
+
getTokenWithPopup(options?: Auth0CompatTokenOptions & Auth0CompatRedirectOptions): Promise<string | undefined>;
|
|
121
|
+
/**
|
|
122
|
+
* Navigate to sign-in. With `authorizationParams.connection` the user goes
|
|
123
|
+
* straight to that social provider; otherwise to the instance's hosted page.
|
|
124
|
+
* `appState` comes back from {@link handleRedirectCallback}.
|
|
125
|
+
*/
|
|
126
|
+
loginWithRedirect(options?: Auth0CompatRedirectOptions): Promise<void>;
|
|
127
|
+
/**
|
|
128
|
+
* Finish a redirect sign-in on the page you came back to: exchanges the
|
|
129
|
+
* one-time ticket in the URL (if any), removes it from the address bar, and
|
|
130
|
+
* returns the `appState` passed to `loginWithRedirect`.
|
|
131
|
+
*/
|
|
132
|
+
handleRedirectCallback(url?: string): Promise<{
|
|
133
|
+
appState?: unknown;
|
|
134
|
+
}>;
|
|
135
|
+
/**
|
|
136
|
+
* Sign in in a popup: straight at a social provider with
|
|
137
|
+
* `authorizationParams.connection`, otherwise the hosted sign-in page (this
|
|
138
|
+
* waits until a session appears or the popup is closed, up to 5 minutes).
|
|
139
|
+
*/
|
|
140
|
+
loginWithPopup(options?: Auth0CompatRedirectOptions & {
|
|
141
|
+
timeoutInSeconds?: number;
|
|
142
|
+
}): Promise<void>;
|
|
143
|
+
private isSignedInNow;
|
|
144
|
+
/** Sign out (revokes the Atlas session), then go to `logoutParams.returnTo` (default: this site). */
|
|
145
|
+
logout(options?: Auth0CompatLogoutOptions): Promise<void>;
|
|
146
|
+
}
|
|
147
|
+
/** `createAuth0Client(options)`: a client that has already checked the session. */
|
|
148
|
+
export declare function createAuth0CompatClient(options: Auth0CompatClientOptions): Promise<Auth0CompatClient>;
|
|
149
|
+
export {};
|
package/dist/compat.js
ADDED
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Auth0CompatClient = exports.Auth0CompatError = void 0;
|
|
4
|
+
exports.decodeJwtPayload = decodeJwtPayload;
|
|
5
|
+
exports.auth0UserFromClient = auth0UserFromClient;
|
|
6
|
+
exports.createAuth0CompatClient = createAuth0CompatClient;
|
|
7
|
+
/**
|
|
8
|
+
* `@atlasauth/js/compat` — a drop-in for `@auth0/auth0-spa-js` on Atlas, for
|
|
9
|
+
* framework-free browser apps (what `atlas migrate code --from auth0` rewrites
|
|
10
|
+
* `createAuth0Client` / `new Auth0Client` onto).
|
|
11
|
+
*
|
|
12
|
+
* The client keeps auth0-spa-js's method names and result shapes —
|
|
13
|
+
* `loginWithRedirect`, `handleRedirectCallback`, `isAuthenticated`, `getUser`,
|
|
14
|
+
* `getTokenSilently`, `logout`, … — on top of the Atlas Frontend API: the session
|
|
15
|
+
* lives in Atlas's own cookies, sign-in happens on your instance's hosted pages
|
|
16
|
+
* (or straight at a social provider when `authorizationParams.connection` is
|
|
17
|
+
* given), and tokens are Atlas session tokens. Move call sites to the native
|
|
18
|
+
* `@atlasauth/js` APIs at your own pace.
|
|
19
|
+
*/
|
|
20
|
+
const fapi_1 = require("./fapi");
|
|
21
|
+
const redirect_1 = require("./redirect");
|
|
22
|
+
const sign_out_1 = require("./sign-out");
|
|
23
|
+
const dev_browser_1 = require("./dev-browser");
|
|
24
|
+
/** auth0-spa-js-style errors: `error` carries the OAuth-ish code apps branch on. */
|
|
25
|
+
class Auth0CompatError extends Error {
|
|
26
|
+
error;
|
|
27
|
+
constructor(error, message) {
|
|
28
|
+
super(message);
|
|
29
|
+
this.error = error;
|
|
30
|
+
this.name = 'Auth0CompatError';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.Auth0CompatError = Auth0CompatError;
|
|
34
|
+
/** Auth0 connection names → Atlas provider keys (others pass through). */
|
|
35
|
+
const CONNECTIONS = {
|
|
36
|
+
'google-oauth2': 'google',
|
|
37
|
+
windowslive: 'microsoft',
|
|
38
|
+
'microsoft-account': 'microsoft',
|
|
39
|
+
github: 'github',
|
|
40
|
+
apple: 'apple',
|
|
41
|
+
facebook: 'facebook',
|
|
42
|
+
linkedin: 'linkedin',
|
|
43
|
+
twitter: 'twitter',
|
|
44
|
+
discord: 'discord',
|
|
45
|
+
gitlab: 'gitlab',
|
|
46
|
+
bitbucket: 'bitbucket',
|
|
47
|
+
};
|
|
48
|
+
const APP_STATE_KEY = 'atlas:compat:appState';
|
|
49
|
+
/** Decode a JWT's payload (no verification: it came from our own FAPI). */
|
|
50
|
+
function decodeJwtPayload(jwt) {
|
|
51
|
+
const part = jwt.split('.')[1];
|
|
52
|
+
if (!part)
|
|
53
|
+
return null;
|
|
54
|
+
try {
|
|
55
|
+
const b64 = part.replace(/-/g, '+').replace(/_/g, '/').padEnd(Math.ceil(part.length / 4) * 4, '=');
|
|
56
|
+
const json = decodeURIComponent(Array.from(atob(b64), (c) => `%${c.charCodeAt(0).toString(16).padStart(2, '0')}`).join(''));
|
|
57
|
+
return JSON.parse(json);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/** Project the Frontend API user onto the OIDC profile shape. */
|
|
64
|
+
function auth0UserFromClient(user) {
|
|
65
|
+
if (!user)
|
|
66
|
+
return undefined;
|
|
67
|
+
const emails = user.email_addresses ?? [];
|
|
68
|
+
const email = emails.find((e) => e.primary) ?? emails.find((e) => e.verified) ?? emails[0];
|
|
69
|
+
const out = { sub: user.id };
|
|
70
|
+
const name = [user.first_name, user.last_name].filter(Boolean).join(' ') || user.username;
|
|
71
|
+
if (name)
|
|
72
|
+
out.name = name;
|
|
73
|
+
if (user.first_name)
|
|
74
|
+
out.given_name = user.first_name;
|
|
75
|
+
if (user.last_name)
|
|
76
|
+
out.family_name = user.last_name;
|
|
77
|
+
if (user.username)
|
|
78
|
+
out.nickname = user.username;
|
|
79
|
+
if (user.image_url)
|
|
80
|
+
out.picture = user.image_url;
|
|
81
|
+
if (email) {
|
|
82
|
+
out.email = email.email_address;
|
|
83
|
+
out.email_verified = email.verified;
|
|
84
|
+
}
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
87
|
+
function frontendApiFrom(options) {
|
|
88
|
+
const raw = options.frontendApi ?? options.domain ?? '';
|
|
89
|
+
if (!raw)
|
|
90
|
+
return '';
|
|
91
|
+
const withScheme = /^https?:\/\//i.test(raw) ? raw : `https://${raw}`;
|
|
92
|
+
return withScheme.replace(/\/+$/, '');
|
|
93
|
+
}
|
|
94
|
+
function withRedirect(url, redirectUrl) {
|
|
95
|
+
if (!redirectUrl)
|
|
96
|
+
return url;
|
|
97
|
+
return `${url}${url.includes('?') ? '&' : '?'}redirect_url=${encodeURIComponent(redirectUrl)}`;
|
|
98
|
+
}
|
|
99
|
+
function currentHref() {
|
|
100
|
+
return typeof window === 'undefined' ? undefined : window.location.href;
|
|
101
|
+
}
|
|
102
|
+
function storage() {
|
|
103
|
+
try {
|
|
104
|
+
return typeof window === 'undefined' ? null : window.sessionStorage;
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/** The auth0-spa-js `Auth0Client`, on Atlas. */
|
|
111
|
+
class Auth0CompatClient {
|
|
112
|
+
publishableKey;
|
|
113
|
+
frontendApi;
|
|
114
|
+
fapi;
|
|
115
|
+
raw;
|
|
116
|
+
options;
|
|
117
|
+
state = null;
|
|
118
|
+
token = null;
|
|
119
|
+
constructor(options) {
|
|
120
|
+
const publishableKey = options.publishableKey ?? options.clientId;
|
|
121
|
+
if (!publishableKey)
|
|
122
|
+
throw new Error('Auth0CompatClient: publishableKey is required.');
|
|
123
|
+
this.publishableKey = publishableKey;
|
|
124
|
+
this.frontendApi = frontendApiFrom(options);
|
|
125
|
+
this.options = options;
|
|
126
|
+
const fetchImpl = options.fetchImpl ?? ((...args) => fetch(...args));
|
|
127
|
+
this.fapi = new fapi_1.FapiClient({ publishableKey, baseUrl: this.frontendApi, fetchImpl });
|
|
128
|
+
const doFetch = (0, dev_browser_1.withDevBrowser)(publishableKey, fetchImpl);
|
|
129
|
+
this.raw = (path, init = {}) => doFetch(`${this.frontendApi}${path}`, {
|
|
130
|
+
...init,
|
|
131
|
+
credentials: 'include',
|
|
132
|
+
headers: {
|
|
133
|
+
'x-publishable-key': publishableKey,
|
|
134
|
+
...(init.body ? { 'content-type': 'application/json' } : {}),
|
|
135
|
+
...init.headers,
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
signInUrl(signUp = false) {
|
|
140
|
+
if (signUp)
|
|
141
|
+
return this.options.signUpUrl ?? `${this.frontendApi}/hosted/sign-up`;
|
|
142
|
+
return this.options.signInUrl ?? `${this.frontendApi}/hosted/sign-in`;
|
|
143
|
+
}
|
|
144
|
+
/** Read the Frontend API client state (session, user, token). */
|
|
145
|
+
async load(force = false) {
|
|
146
|
+
if (!force && this.state && Date.now() - this.state.at < 2_000)
|
|
147
|
+
return this.state.body;
|
|
148
|
+
const response = await this.raw('/v1/client');
|
|
149
|
+
if (!response.ok)
|
|
150
|
+
throw new Error(`Atlas: could not read the session (HTTP ${response.status}).`);
|
|
151
|
+
const body = (await response.json());
|
|
152
|
+
this.state = { body, at: Date.now() };
|
|
153
|
+
if (body.session && body.jwt)
|
|
154
|
+
this.keepToken(body.jwt, body.session.id);
|
|
155
|
+
if (!body.session)
|
|
156
|
+
this.token = null;
|
|
157
|
+
return body;
|
|
158
|
+
}
|
|
159
|
+
keepToken(jwt, sessionId) {
|
|
160
|
+
const exp = Number(decodeJwtPayload(jwt)?.exp ?? 0) * 1000;
|
|
161
|
+
this.token = { jwt, exp, sessionId };
|
|
162
|
+
}
|
|
163
|
+
/** `checkSession()`: refresh the local view of the session; never throws. */
|
|
164
|
+
async checkSession() {
|
|
165
|
+
try {
|
|
166
|
+
await this.load(true);
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
// auth0-spa-js swallows login_required here too.
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
async isAuthenticated() {
|
|
173
|
+
const body = await this.load();
|
|
174
|
+
return Boolean(body.session && body.user);
|
|
175
|
+
}
|
|
176
|
+
async getUser() {
|
|
177
|
+
const body = await this.load();
|
|
178
|
+
return body.session ? auth0UserFromClient(body.user) : undefined;
|
|
179
|
+
}
|
|
180
|
+
async getIdTokenClaims() {
|
|
181
|
+
const jwt = await this.getTokenSilently().catch(() => null);
|
|
182
|
+
if (typeof jwt !== 'string')
|
|
183
|
+
return undefined;
|
|
184
|
+
const claims = decodeJwtPayload(jwt);
|
|
185
|
+
return claims ? { ...claims, __raw: jwt } : undefined;
|
|
186
|
+
}
|
|
187
|
+
async getTokenSilently(options = {}) {
|
|
188
|
+
const body = await this.load(options.cacheMode === 'off');
|
|
189
|
+
if (!body.session)
|
|
190
|
+
throw new Auth0CompatError('login_required', 'Login required');
|
|
191
|
+
let jwt = null;
|
|
192
|
+
let expiresIn = 0;
|
|
193
|
+
if (options.template) {
|
|
194
|
+
const t = await (0, fapi_1.getTemplateToken)(this.fapi, body.session.id, options.template);
|
|
195
|
+
if (!t)
|
|
196
|
+
throw new Auth0CompatError('login_required', `No token for template ${options.template}`);
|
|
197
|
+
jwt = t.jwt;
|
|
198
|
+
expiresIn = t.expiresIn;
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
const usable = this.token && this.token.sessionId === body.session.id && this.token.exp - Date.now() > 10_000;
|
|
202
|
+
if (!usable || options.cacheMode === 'off') {
|
|
203
|
+
if (options.cacheMode === 'cache-only')
|
|
204
|
+
throw new Auth0CompatError('login_required', 'No cached token');
|
|
205
|
+
const response = await this.raw(`/v1/client/sessions/${encodeURIComponent(body.session.id)}/tokens`, { method: 'POST' });
|
|
206
|
+
if (!response.ok)
|
|
207
|
+
throw new Auth0CompatError('login_required', 'Login required');
|
|
208
|
+
const minted = (await response.json());
|
|
209
|
+
this.keepToken(minted.jwt, minted.session_id);
|
|
210
|
+
}
|
|
211
|
+
jwt = this.token.jwt;
|
|
212
|
+
expiresIn = Math.max(0, Math.floor((this.token.exp - Date.now()) / 1000));
|
|
213
|
+
}
|
|
214
|
+
return options.detailedResponse ? { access_token: jwt, id_token: jwt, expires_in: expiresIn } : jwt;
|
|
215
|
+
}
|
|
216
|
+
/** Sign in in a popup when needed, then return a token. */
|
|
217
|
+
async getTokenWithPopup(options = {}) {
|
|
218
|
+
if (!(await this.isAuthenticated()))
|
|
219
|
+
await this.loginWithPopup(options);
|
|
220
|
+
return this.getTokenSilently({ ...options, detailedResponse: false });
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Navigate to sign-in. With `authorizationParams.connection` the user goes
|
|
224
|
+
* straight to that social provider; otherwise to the instance's hosted page.
|
|
225
|
+
* `appState` comes back from {@link handleRedirectCallback}.
|
|
226
|
+
*/
|
|
227
|
+
async loginWithRedirect(options = {}) {
|
|
228
|
+
const params = options.authorizationParams ?? {};
|
|
229
|
+
const returnTo = params.redirect_uri ?? this.options.authorizationParams?.redirect_uri ?? currentHref();
|
|
230
|
+
if (options.appState !== undefined)
|
|
231
|
+
storage()?.setItem(APP_STATE_KEY, JSON.stringify(options.appState));
|
|
232
|
+
let url;
|
|
233
|
+
if (params.connection) {
|
|
234
|
+
const started = await (0, redirect_1.startOauthRedirect)(this.fapi, {
|
|
235
|
+
provider: CONNECTIONS[params.connection] ?? params.connection,
|
|
236
|
+
redirectUrl: returnTo ?? '/',
|
|
237
|
+
});
|
|
238
|
+
if (!started)
|
|
239
|
+
throw new Auth0CompatError('start_failed', `Could not start sign-in with ${params.connection}.`);
|
|
240
|
+
url = started.authorizationUrl;
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
url = withRedirect(this.signInUrl(params.screen_hint === 'signup'), returnTo);
|
|
244
|
+
}
|
|
245
|
+
if (options.openUrl)
|
|
246
|
+
await options.openUrl(url);
|
|
247
|
+
else if (typeof window !== 'undefined')
|
|
248
|
+
window.location.assign(url);
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Finish a redirect sign-in on the page you came back to: exchanges the
|
|
252
|
+
* one-time ticket in the URL (if any), removes it from the address bar, and
|
|
253
|
+
* returns the `appState` passed to `loginWithRedirect`.
|
|
254
|
+
*/
|
|
255
|
+
async handleRedirectCallback(url) {
|
|
256
|
+
const href = url ?? currentHref() ?? '';
|
|
257
|
+
const search = href.includes('?') ? href.slice(href.indexOf('?')) : '';
|
|
258
|
+
const result = (0, redirect_1.readRedirectResult)(search.split('#')[0] ?? '');
|
|
259
|
+
if (result?.ticket) {
|
|
260
|
+
const response = await this.raw('/v1/client/tickets/exchange', {
|
|
261
|
+
method: 'POST',
|
|
262
|
+
body: JSON.stringify({ attempt_id: result.attemptId, ticket: result.ticket }),
|
|
263
|
+
});
|
|
264
|
+
if (!response.ok)
|
|
265
|
+
throw new Auth0CompatError('login_required', 'The sign-in could not be completed.');
|
|
266
|
+
}
|
|
267
|
+
else if (result?.status && result.status !== 'complete') {
|
|
268
|
+
throw new Auth0CompatError('login_required', `Sign-in needs another step (${result.status}).`);
|
|
269
|
+
}
|
|
270
|
+
if (!url && typeof window !== 'undefined' && result) {
|
|
271
|
+
window.history.replaceState({}, document.title, (0, redirect_1.stripRedirectParams)(window.location.href));
|
|
272
|
+
}
|
|
273
|
+
await this.load(true);
|
|
274
|
+
const raw = storage()?.getItem(APP_STATE_KEY);
|
|
275
|
+
storage()?.removeItem(APP_STATE_KEY);
|
|
276
|
+
let appState;
|
|
277
|
+
try {
|
|
278
|
+
appState = raw ? JSON.parse(raw) : undefined;
|
|
279
|
+
}
|
|
280
|
+
catch {
|
|
281
|
+
appState = undefined;
|
|
282
|
+
}
|
|
283
|
+
return appState === undefined ? {} : { appState };
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Sign in in a popup: straight at a social provider with
|
|
287
|
+
* `authorizationParams.connection`, otherwise the hosted sign-in page (this
|
|
288
|
+
* waits until a session appears or the popup is closed, up to 5 minutes).
|
|
289
|
+
*/
|
|
290
|
+
async loginWithPopup(options = {}) {
|
|
291
|
+
const params = options.authorizationParams ?? {};
|
|
292
|
+
if (params.connection) {
|
|
293
|
+
const outcome = await (0, redirect_1.startOauthPopup)(this.fapi, {
|
|
294
|
+
provider: CONNECTIONS[params.connection] ?? params.connection,
|
|
295
|
+
redirectUrl: currentHref() ?? '/',
|
|
296
|
+
});
|
|
297
|
+
if (outcome.blocked)
|
|
298
|
+
throw new Auth0CompatError('popup_blocked', 'The sign-in popup was blocked.');
|
|
299
|
+
if (outcome.ticket && outcome.attemptId) {
|
|
300
|
+
await this.raw('/v1/client/tickets/exchange', {
|
|
301
|
+
method: 'POST',
|
|
302
|
+
body: JSON.stringify({ attempt_id: outcome.attemptId, ticket: outcome.ticket }),
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
else if (!outcome.sessionDetected) {
|
|
306
|
+
throw new Auth0CompatError(outcome.error === 'popup_closed' ? 'popup_closed' : 'start_failed', outcome.error ?? 'Sign-in did not complete.');
|
|
307
|
+
}
|
|
308
|
+
await this.load(true);
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
const popup = typeof window !== 'undefined' ? window.open(this.signInUrl(params.screen_hint === 'signup'), 'atlas-sign-in', 'width=500,height=650') : null;
|
|
312
|
+
if (!popup)
|
|
313
|
+
throw new Auth0CompatError('popup_blocked', 'The sign-in popup was blocked.');
|
|
314
|
+
const deadline = Date.now() + (options.timeoutInSeconds ?? 300) * 1000;
|
|
315
|
+
for (;;) {
|
|
316
|
+
await new Promise((r) => setTimeout(r, 1_000));
|
|
317
|
+
if (await this.isSignedInNow()) {
|
|
318
|
+
try {
|
|
319
|
+
popup.close();
|
|
320
|
+
}
|
|
321
|
+
catch {
|
|
322
|
+
/* cross-origin close */
|
|
323
|
+
}
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
if (popup.closed)
|
|
327
|
+
throw new Auth0CompatError('popup_closed', 'The sign-in popup was closed.');
|
|
328
|
+
if (Date.now() > deadline)
|
|
329
|
+
throw new Auth0CompatError('timeout', 'Timed out waiting for sign-in.');
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
async isSignedInNow() {
|
|
333
|
+
try {
|
|
334
|
+
return Boolean((await this.load(true)).session);
|
|
335
|
+
}
|
|
336
|
+
catch {
|
|
337
|
+
return false;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
/** Sign out (revokes the Atlas session), then go to `logoutParams.returnTo` (default: this site). */
|
|
341
|
+
async logout(options = {}) {
|
|
342
|
+
const body = this.state?.body ?? (await this.load().catch(() => null));
|
|
343
|
+
if (body?.session)
|
|
344
|
+
await (0, sign_out_1.revokeSession)(this.raw, body.session.id);
|
|
345
|
+
this.state = null;
|
|
346
|
+
this.token = null;
|
|
347
|
+
const url = options.logoutParams?.returnTo ?? (typeof window !== 'undefined' ? window.location.origin : '/');
|
|
348
|
+
if (options.openUrl === false)
|
|
349
|
+
return;
|
|
350
|
+
if (typeof options.openUrl === 'function')
|
|
351
|
+
await options.openUrl(url);
|
|
352
|
+
else if (typeof window !== 'undefined')
|
|
353
|
+
window.location.assign(url);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
exports.Auth0CompatClient = Auth0CompatClient;
|
|
357
|
+
/** `createAuth0Client(options)`: a client that has already checked the session. */
|
|
358
|
+
async function createAuth0CompatClient(options) {
|
|
359
|
+
const client = new Auth0CompatClient(options);
|
|
360
|
+
await client.checkSession();
|
|
361
|
+
return client;
|
|
362
|
+
}
|
|
363
|
+
//# sourceMappingURL=compat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compat.js","sourceRoot":"","sources":["../src/compat.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { FapiClient } from './fapi';
|
|
2
|
+
/**
|
|
3
|
+
* Device sign-in (OAuth 2.0 Device Authorization Grant, RFC 8628) from YOUR app:
|
|
4
|
+
* the signed-in user types — or scans — the code their TV, console or CLI shows,
|
|
5
|
+
* and your own page approves it. The alternative to sending them to Atlas's
|
|
6
|
+
* hosted `/oauth2/device` page.
|
|
7
|
+
*
|
|
8
|
+
* const auth = await lookupDeviceAuthorization(client, typedCode);
|
|
9
|
+
* // show auth.client.name and auth.scopes, then:
|
|
10
|
+
* await approveDeviceAuthorization(client, auth); // or denyDeviceAuthorization
|
|
11
|
+
*
|
|
12
|
+
* The calls use the signed-in session (the cookie, or a native app's session
|
|
13
|
+
* token). When the application requires a recent re-authentication to approve a
|
|
14
|
+
* device (`requiresStepUp`), a stale session gets a
|
|
15
|
+
* {@link DeviceAuthorizationError} with `needsReverification` — re-authenticate
|
|
16
|
+
* (`reauthenticate()`), then approve again.
|
|
17
|
+
*/
|
|
18
|
+
export interface DeviceAuthorizationScope {
|
|
19
|
+
scope: string;
|
|
20
|
+
/** A human description for the consent text. */
|
|
21
|
+
description: string;
|
|
22
|
+
}
|
|
23
|
+
export interface DeviceAuthorization {
|
|
24
|
+
object: 'device_authorization';
|
|
25
|
+
id: string;
|
|
26
|
+
/** The code as the device shows it, e.g. `WDJB-MJHT`. */
|
|
27
|
+
userCode: string;
|
|
28
|
+
status: 'pending' | 'approved' | 'denied';
|
|
29
|
+
client: {
|
|
30
|
+
clientId: string;
|
|
31
|
+
name: string;
|
|
32
|
+
logoUrl: string | null;
|
|
33
|
+
homepageUrl: string | null;
|
|
34
|
+
firstParty: boolean;
|
|
35
|
+
};
|
|
36
|
+
scopes: DeviceAuthorizationScope[];
|
|
37
|
+
/** The API the device asked for a token for, if any. */
|
|
38
|
+
audience: string | null;
|
|
39
|
+
/** Approving needs a recent re-authentication. */
|
|
40
|
+
requiresStepUp: boolean;
|
|
41
|
+
createdAt: number;
|
|
42
|
+
expiresAt: number;
|
|
43
|
+
}
|
|
44
|
+
/** A refused request. `code` is the server's stable error code (`NOT_FOUND`, `RATE_LIMITED`, `STEP_UP_REQUIRED`, …). */
|
|
45
|
+
export declare class DeviceAuthorizationError extends Error {
|
|
46
|
+
readonly code: string;
|
|
47
|
+
readonly status: number;
|
|
48
|
+
readonly param?: string;
|
|
49
|
+
readonly reason?: string;
|
|
50
|
+
readonly meta?: Record<string, unknown>;
|
|
51
|
+
constructor(status: number, code: string, message: string, param?: string, reason?: string, meta?: Record<string, unknown>);
|
|
52
|
+
/** True when approving needs a fresh re-authentication first. */
|
|
53
|
+
get needsReverification(): boolean;
|
|
54
|
+
/** True when the code is unknown, expired or already used. */
|
|
55
|
+
get isInvalidCode(): boolean;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Normalise what a person typed into the `XXXX-XXXX` form devices show:
|
|
59
|
+
* uppercase, spaces and dashes ignored. Returns the input unchanged when it is
|
|
60
|
+
* not 8 letters or digits, so the server answers "not valid".
|
|
61
|
+
*/
|
|
62
|
+
export declare function formatUserCode(input: string): string;
|
|
63
|
+
/** Read a `user_code` from a verification URL the device displayed (`?user_code=`), if any. */
|
|
64
|
+
export declare function userCodeFromUrl(url: string | URL): string | null;
|
|
65
|
+
/** Look up a pending device sign-in by the code the device shows. */
|
|
66
|
+
export declare function lookupDeviceAuthorization(client: FapiClient, userCode: string): Promise<DeviceAuthorization>;
|
|
67
|
+
/** Approve the device sign-in for the signed-in user. The device's next poll receives its tokens. */
|
|
68
|
+
export declare function approveDeviceAuthorization(client: FapiClient, authorization: Pick<DeviceAuthorization, 'id' | 'userCode'>): Promise<DeviceAuthorization>;
|
|
69
|
+
/** Deny the device sign-in. The device's next poll is told `access_denied`. */
|
|
70
|
+
export declare function denyDeviceAuthorization(client: FapiClient, authorization: Pick<DeviceAuthorization, 'id' | 'userCode'>): Promise<DeviceAuthorization>;
|