@atlasauth/capacitor 0.1.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/README.md +118 -0
- package/dist/index.d.ts +116 -0
- package/dist/index.js +155 -0
- package/dist/index.js.map +1 -0
- package/dist/native-session.d.ts +46 -0
- package/dist/native-session.js +56 -0
- package/dist/native-session.js.map +1 -0
- package/dist/pkce.d.ts +34 -0
- package/dist/pkce.js +50 -0
- package/dist/pkce.js.map +1 -0
- package/dist/plugins.d.ts +80 -0
- package/dist/plugins.js +102 -0
- package/dist/plugins.js.map +1 -0
- package/dist/sign-in.d.ts +153 -0
- package/dist/sign-in.js +251 -0
- package/dist/sign-in.js.map +1 -0
- package/dist/token-store.d.ts +63 -0
- package/dist/token-store.js +70 -0
- package/dist/token-store.js.map +1 -0
- package/package.json +56 -0
package/README.md
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# @atlasauth/capacitor
|
|
2
|
+
|
|
3
|
+
The official Atlas SDK for **Capacitor / Ionic** — the cross-platform
|
|
4
|
+
(iOS · Android · web) native-auth sibling of [`@atlasauth/electron`](../electron)
|
|
5
|
+
and [`@atlasauth/expo`](../expo). It gives a Capacitor app the **native-session
|
|
6
|
+
sign-in flow**: system browser → deep-link callback → PKCE → a cookie-free Atlas
|
|
7
|
+
session that auto-refreshes and persists in secure storage.
|
|
8
|
+
|
|
9
|
+
A Capacitor app is a web layer (a WebView on device, a real browser on the web
|
|
10
|
+
target) with no cookie against the Atlas FAPI origin, so it cannot carry a
|
|
11
|
+
session the way a web page does. Instead it signs in through the **system
|
|
12
|
+
browser**, catches the **deep-link** callback, completes **PKCE**, trades the
|
|
13
|
+
code for an Atlas session, and carries that session itself as a bearer — wrapping
|
|
14
|
+
the same `@atlasauth/js` `NativeSessionManager` / `exchangeForSession` /
|
|
15
|
+
`refreshNativeSession` core the Electron and Expo SDKs use.
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
npm install @atlasauth/capacitor
|
|
21
|
+
npx cap sync
|
|
22
|
+
# the Capacitor plugins it drives (all optional peers — install what you use):
|
|
23
|
+
npm install @capacitor/browser @capacitor/app @capacitor/preferences
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`@capacitor/core`, `@capacitor/browser`, `@capacitor/app` and
|
|
27
|
+
`@capacitor/preferences` are **optional peers**. The package compiles and runs
|
|
28
|
+
without them (falling back gracefully), but the native sign-in flow needs
|
|
29
|
+
`@capacitor/browser` + `@capacitor/app`, and persistence needs a token store.
|
|
30
|
+
|
|
31
|
+
### Deep-link setup
|
|
32
|
+
|
|
33
|
+
Register your custom scheme so the authorize redirect reopens the app, and route
|
|
34
|
+
`appUrlOpen` to Atlas:
|
|
35
|
+
|
|
36
|
+
- iOS: add the scheme under `CFBundleURLTypes` in `Info.plist`.
|
|
37
|
+
- Android: add an `intent-filter` with your scheme to the main activity.
|
|
38
|
+
|
|
39
|
+
Your `redirectUri` is that scheme, e.g. `com.acme.app://auth`.
|
|
40
|
+
|
|
41
|
+
## Quick start
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import { createAtlasCapacitor } from '@atlasauth/capacitor';
|
|
45
|
+
|
|
46
|
+
export const atlas = await createAtlasCapacitor({
|
|
47
|
+
publishableKey: 'pk_live_…',
|
|
48
|
+
frontendApi: 'https://fapi.your-instance.atlasauth.net',
|
|
49
|
+
clientId: 'client_…', // your first-party native OAuth client
|
|
50
|
+
redirectUri: 'com.acme.app://auth',
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Sign in (opens the system browser; resolves once the deep link returns).
|
|
54
|
+
await atlas.signIn();
|
|
55
|
+
|
|
56
|
+
// Call your own API with the live, auto-refreshing session.
|
|
57
|
+
const res = await fetch('/api/thing', { headers: await atlas.authHeaders() });
|
|
58
|
+
|
|
59
|
+
atlas.onChange((session) => console.log('session rotated', session.sessionId));
|
|
60
|
+
await atlas.signOut();
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`frontendApi` is required — the publishable key encodes the instance id but not a
|
|
64
|
+
host. Use `https://atlasauth.net` before you verify a custom domain, your custom
|
|
65
|
+
domain after.
|
|
66
|
+
|
|
67
|
+
### The handle
|
|
68
|
+
|
|
69
|
+
| Method | What it does |
|
|
70
|
+
| --- | --- |
|
|
71
|
+
| `signIn({ redirectUri?, scope? })` | System browser → deep-link callback → PKCE → session. On the web target, falls back to the standard redirect (see below). |
|
|
72
|
+
| `handleRedirectCallback(url?)` | Finish a **web** redirect sign-in on app load. |
|
|
73
|
+
| `signOut()` | Forget the session and clear the store. |
|
|
74
|
+
| `getToken()` | The current session JWT, auto-refreshed near expiry. |
|
|
75
|
+
| `authHeaders()` | `{ Authorization, 'x-publishable-key' }` for `/v1/client/me/*` and your API. |
|
|
76
|
+
| `getSession()` | The current `NativeSession`, or null. |
|
|
77
|
+
| `onChange(listener)` | Fires on every session change; returns an unsubscribe. |
|
|
78
|
+
|
|
79
|
+
## Web target (PWA)
|
|
80
|
+
|
|
81
|
+
On the web, there is no deep link, so `signIn()` falls back to the **standard
|
|
82
|
+
redirect**: it stashes the PKCE verifier and navigates to the authorize URL.
|
|
83
|
+
Finish on the next load:
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
// on app boot, when the URL looks like your callback:
|
|
87
|
+
const session = await atlas.handleRedirectCallback(); // defaults to window.location.href
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Secure storage
|
|
91
|
+
|
|
92
|
+
By default the session is persisted with `@capacitor/preferences` when that
|
|
93
|
+
plugin is present, else a non-persistent in-memory store.
|
|
94
|
+
|
|
95
|
+
> ⚠️ **`@capacitor/preferences` is plaintext at rest** (UserDefaults /
|
|
96
|
+
> SharedPreferences). For production, back the store with a secure-storage
|
|
97
|
+
> community plugin (e.g. `@capacitor-community/secure-storage`) behind the same
|
|
98
|
+
> `TokenStore` interface:
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
import { createAtlasCapacitor, type TokenStore } from '@atlasauth/capacitor';
|
|
102
|
+
|
|
103
|
+
const secureStore: TokenStore = {
|
|
104
|
+
getToken: () => SecureStorage.get('atlas.session'),
|
|
105
|
+
setToken: (v) => SecureStorage.set('atlas.session', v),
|
|
106
|
+
clearToken: () => SecureStorage.remove('atlas.session'),
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const atlas = await createAtlasCapacitor({ /* … */ storage: secureStore });
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Driving the pieces yourself
|
|
113
|
+
|
|
114
|
+
The flow is also exposed à la carte: `createPkcePair`, `buildAuthorizeUrl`,
|
|
115
|
+
`parseAuthCallback`, `redeemAuthorizationCode`, `exchangeAuthCode`,
|
|
116
|
+
`signInWithBrowser`, `completeRedirectSignIn`, plus
|
|
117
|
+
`createNativeSessionManager` / `exchangeForSession` / `refreshNativeSession`
|
|
118
|
+
re-exported from [`@atlasauth/js`](../js).
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@atlasauth/capacitor` — the Atlas SDK for Capacitor / Ionic.
|
|
3
|
+
*
|
|
4
|
+
* A Capacitor app is a web layer (WebView on iOS/Android, a real browser on the
|
|
5
|
+
* web target) with no cookie against the Atlas FAPI origin, so it cannot carry a
|
|
6
|
+
* session the way a web page does. This package gives it the NATIVE-session flow
|
|
7
|
+
* instead: sign in through the SYSTEM browser, catch the deep-link callback,
|
|
8
|
+
* complete PKCE, trade the code for a cookie-free Atlas session, and keep that
|
|
9
|
+
* session live — auto-refreshing the short-lived JWT and persisting each rotated
|
|
10
|
+
* refresh token into secure storage. It is the Capacitor sibling of
|
|
11
|
+
* `@atlasauth/electron` and `@atlasauth/expo`, wrapping the very same
|
|
12
|
+
* `@atlasauth/js` `NativeSessionManager` / `exchangeForSession` /
|
|
13
|
+
* `refreshNativeSession` core.
|
|
14
|
+
*
|
|
15
|
+
* The one call an app makes is {@link createAtlasCapacitor}; everything else here
|
|
16
|
+
* (the sign-in flow, the token store, the PKCE helpers) is exposed for apps that
|
|
17
|
+
* want to drive the pieces themselves.
|
|
18
|
+
*/
|
|
19
|
+
import type { NativeSession, NativeSessionManager } from '@atlasauth/js';
|
|
20
|
+
import { type CapacitorPlugins } from './plugins';
|
|
21
|
+
import { type SignInOutcome } from './sign-in';
|
|
22
|
+
import { type TokenStore } from './token-store';
|
|
23
|
+
export interface CreateAtlasCapacitorConfig {
|
|
24
|
+
/** The instance publishable key (`pk_…`). */
|
|
25
|
+
publishableKey: string;
|
|
26
|
+
/** The instance's FAPI origin, e.g. `https://fapi.acme.atlasauth.net`. */
|
|
27
|
+
frontendApi: string;
|
|
28
|
+
/** The first-party native OAuth client id. Required to {@link AtlasCapacitor.signIn}. */
|
|
29
|
+
clientId?: string;
|
|
30
|
+
/** The app's custom-scheme callback, e.g. `com.acme.app://auth`. A {@link AtlasCapacitor.signIn} default. */
|
|
31
|
+
redirectUri?: string;
|
|
32
|
+
/** Space-delimited OAuth scopes. A {@link AtlasCapacitor.signIn} default. */
|
|
33
|
+
scope?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Where the rotated session is persisted. Defaults to a `@capacitor/preferences`
|
|
36
|
+
* store when the plugin is present, else a NON-persistent in-memory store. Ship
|
|
37
|
+
* a secure-storage-backed {@link TokenStore} in production — Preferences is
|
|
38
|
+
* plaintext at rest.
|
|
39
|
+
*/
|
|
40
|
+
storage?: TokenStore;
|
|
41
|
+
/** Where the transient PKCE material is stashed on the WEB redirect path. */
|
|
42
|
+
pkceStore?: TokenStore;
|
|
43
|
+
/** Inject the Capacitor plugins (tests). Defaults to a lazy, guarded load. */
|
|
44
|
+
plugins?: CapacitorPlugins;
|
|
45
|
+
/** Injectable for tests; defaults to the platform `fetch`. */
|
|
46
|
+
fetchImpl?: typeof fetch;
|
|
47
|
+
/** Injectable clock, epoch ms. Defaults to `Date.now`. */
|
|
48
|
+
now?: () => number;
|
|
49
|
+
/** Navigate the page on the web redirect path. @default `window.location.assign` */
|
|
50
|
+
navigate?: (url: string) => void;
|
|
51
|
+
}
|
|
52
|
+
/** Per-call overrides for {@link AtlasCapacitor.signIn}. */
|
|
53
|
+
export interface SignInOptions {
|
|
54
|
+
clientId?: string;
|
|
55
|
+
redirectUri?: string;
|
|
56
|
+
scope?: string;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The Atlas handle a Capacitor app holds. Wraps the `@atlasauth/js`
|
|
60
|
+
* {@link NativeSessionManager}: {@link signIn} runs the browser flow and seeds
|
|
61
|
+
* the manager, {@link getToken} hands out a live (auto-refreshing) JWT, and
|
|
62
|
+
* {@link onChange} fires on every session change.
|
|
63
|
+
*/
|
|
64
|
+
export interface AtlasCapacitor {
|
|
65
|
+
/**
|
|
66
|
+
* Run the native-session sign-in: open the system browser, catch the deep-link
|
|
67
|
+
* callback, complete PKCE, exchange for a session, and store it. On the web
|
|
68
|
+
* target it falls back to the standard redirect (navigates away, `pending:
|
|
69
|
+
* true`) — finish with {@link handleRedirectCallback} on the next load.
|
|
70
|
+
*/
|
|
71
|
+
signIn(options?: SignInOptions): Promise<SignInOutcome>;
|
|
72
|
+
/**
|
|
73
|
+
* Finish a WEB redirect sign-in on app load: read the callback `url` (defaults
|
|
74
|
+
* to `window.location.href`), complete PKCE, store the session, and return it
|
|
75
|
+
* (or null when there is nothing to complete).
|
|
76
|
+
*/
|
|
77
|
+
handleRedirectCallback(url?: string): Promise<NativeSession | null>;
|
|
78
|
+
/** Forget the session and clear the store (sign-out). */
|
|
79
|
+
signOut(): Promise<void>;
|
|
80
|
+
/** The current session JWT, auto-refreshed near expiry; null when signed out. */
|
|
81
|
+
getToken(): Promise<string | null>;
|
|
82
|
+
/** The headers an authenticated `/v1/client/me/*` call needs (bearer + pk). */
|
|
83
|
+
authHeaders(): Promise<Record<string, string>>;
|
|
84
|
+
/** The current session, or null when signed out. Does NOT refresh. */
|
|
85
|
+
getSession(): NativeSession | null;
|
|
86
|
+
/** Register a listener fired with the session on every change; returns unsubscribe. */
|
|
87
|
+
onChange(listener: (session: NativeSession) => void): () => void;
|
|
88
|
+
/** The underlying `@atlasauth/js` manager, for advanced use. */
|
|
89
|
+
readonly manager: NativeSessionManager;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Create the Atlas handle for a Capacitor app.
|
|
93
|
+
*
|
|
94
|
+
* Async because it lazily loads the Capacitor plugins and rehydrates the session
|
|
95
|
+
* manager from the store, so a returning user is signed in before the first
|
|
96
|
+
* request. Call it once at startup and keep the result.
|
|
97
|
+
*
|
|
98
|
+
* ```ts
|
|
99
|
+
* import { createAtlasCapacitor } from '@atlasauth/capacitor';
|
|
100
|
+
*
|
|
101
|
+
* const atlas = await createAtlasCapacitor({
|
|
102
|
+
* publishableKey: 'pk_live_…',
|
|
103
|
+
* frontendApi: 'https://fapi.acme.atlasauth.net',
|
|
104
|
+
* clientId: 'client_…',
|
|
105
|
+
* redirectUri: 'com.acme.app://auth',
|
|
106
|
+
* });
|
|
107
|
+
* await atlas.signIn();
|
|
108
|
+
* const token = await atlas.getToken();
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
export declare function createAtlasCapacitor(config: CreateAtlasCapacitorConfig): Promise<AtlasCapacitor>;
|
|
112
|
+
export * from './plugins';
|
|
113
|
+
export * from './pkce';
|
|
114
|
+
export * from './token-store';
|
|
115
|
+
export * from './sign-in';
|
|
116
|
+
export { createNativeSessionManager, clearNativeSession, NativeSessionManager, exchangeForSession, refreshNativeSession, type NativeSession, type NativeSessionConfig, } from './native-session';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* `@atlasauth/capacitor` — the Atlas SDK for Capacitor / Ionic.
|
|
4
|
+
*
|
|
5
|
+
* A Capacitor app is a web layer (WebView on iOS/Android, a real browser on the
|
|
6
|
+
* web target) with no cookie against the Atlas FAPI origin, so it cannot carry a
|
|
7
|
+
* session the way a web page does. This package gives it the NATIVE-session flow
|
|
8
|
+
* instead: sign in through the SYSTEM browser, catch the deep-link callback,
|
|
9
|
+
* complete PKCE, trade the code for a cookie-free Atlas session, and keep that
|
|
10
|
+
* session live — auto-refreshing the short-lived JWT and persisting each rotated
|
|
11
|
+
* refresh token into secure storage. It is the Capacitor sibling of
|
|
12
|
+
* `@atlasauth/electron` and `@atlasauth/expo`, wrapping the very same
|
|
13
|
+
* `@atlasauth/js` `NativeSessionManager` / `exchangeForSession` /
|
|
14
|
+
* `refreshNativeSession` core.
|
|
15
|
+
*
|
|
16
|
+
* The one call an app makes is {@link createAtlasCapacitor}; everything else here
|
|
17
|
+
* (the sign-in flow, the token store, the PKCE helpers) is exposed for apps that
|
|
18
|
+
* want to drive the pieces themselves.
|
|
19
|
+
*/
|
|
20
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
21
|
+
if (k2 === undefined) k2 = k;
|
|
22
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
23
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
24
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
25
|
+
}
|
|
26
|
+
Object.defineProperty(o, k2, desc);
|
|
27
|
+
}) : (function(o, m, k, k2) {
|
|
28
|
+
if (k2 === undefined) k2 = k;
|
|
29
|
+
o[k2] = m[k];
|
|
30
|
+
}));
|
|
31
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
32
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
33
|
+
};
|
|
34
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
|
+
exports.refreshNativeSession = exports.exchangeForSession = exports.NativeSessionManager = exports.clearNativeSession = exports.createNativeSessionManager = void 0;
|
|
36
|
+
exports.createAtlasCapacitor = createAtlasCapacitor;
|
|
37
|
+
const plugins_1 = require("./plugins");
|
|
38
|
+
const sign_in_1 = require("./sign-in");
|
|
39
|
+
const token_store_1 = require("./token-store");
|
|
40
|
+
const native_session_1 = require("./native-session");
|
|
41
|
+
/**
|
|
42
|
+
* Create the Atlas handle for a Capacitor app.
|
|
43
|
+
*
|
|
44
|
+
* Async because it lazily loads the Capacitor plugins and rehydrates the session
|
|
45
|
+
* manager from the store, so a returning user is signed in before the first
|
|
46
|
+
* request. Call it once at startup and keep the result.
|
|
47
|
+
*
|
|
48
|
+
* ```ts
|
|
49
|
+
* import { createAtlasCapacitor } from '@atlasauth/capacitor';
|
|
50
|
+
*
|
|
51
|
+
* const atlas = await createAtlasCapacitor({
|
|
52
|
+
* publishableKey: 'pk_live_…',
|
|
53
|
+
* frontendApi: 'https://fapi.acme.atlasauth.net',
|
|
54
|
+
* clientId: 'client_…',
|
|
55
|
+
* redirectUri: 'com.acme.app://auth',
|
|
56
|
+
* });
|
|
57
|
+
* await atlas.signIn();
|
|
58
|
+
* const token = await atlas.getToken();
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
async function createAtlasCapacitor(config) {
|
|
62
|
+
const plugins = config.plugins ?? (await (0, plugins_1.loadCapacitorPlugins)());
|
|
63
|
+
const storage = config.storage ??
|
|
64
|
+
(plugins.Preferences
|
|
65
|
+
? (0, token_store_1.createPreferencesTokenStore)(plugins.Preferences, token_store_1.DEFAULT_SESSION_KEY)
|
|
66
|
+
: (0, token_store_1.createInMemoryTokenStore)());
|
|
67
|
+
const pkceStore = config.pkceStore ??
|
|
68
|
+
(plugins.Preferences
|
|
69
|
+
? (0, token_store_1.createPreferencesTokenStore)(plugins.Preferences, sign_in_1.PKCE_STASH_KEY)
|
|
70
|
+
: (0, token_store_1.createInMemoryTokenStore)());
|
|
71
|
+
const manager = await (0, native_session_1.createNativeSessionManager)({
|
|
72
|
+
frontendApi: config.frontendApi,
|
|
73
|
+
publishableKey: config.publishableKey,
|
|
74
|
+
clientId: config.clientId,
|
|
75
|
+
storage,
|
|
76
|
+
fetchImpl: config.fetchImpl,
|
|
77
|
+
now: config.now,
|
|
78
|
+
});
|
|
79
|
+
const requireString = (value, name) => {
|
|
80
|
+
if (!value)
|
|
81
|
+
throw new Error(`Atlas: \`${name}\` is required to sign in.`);
|
|
82
|
+
return value;
|
|
83
|
+
};
|
|
84
|
+
return {
|
|
85
|
+
manager,
|
|
86
|
+
async signIn(options = {}) {
|
|
87
|
+
const clientId = requireString(options.clientId ?? config.clientId, 'clientId');
|
|
88
|
+
const redirectUri = requireString(options.redirectUri ?? config.redirectUri, 'redirectUri');
|
|
89
|
+
const outcome = await (0, sign_in_1.signInWithBrowser)({
|
|
90
|
+
frontendApi: config.frontendApi,
|
|
91
|
+
clientId,
|
|
92
|
+
redirectUri,
|
|
93
|
+
scope: options.scope ?? config.scope,
|
|
94
|
+
browser: plugins.Browser,
|
|
95
|
+
app: plugins.App,
|
|
96
|
+
capacitor: plugins.Capacitor,
|
|
97
|
+
pkceStore,
|
|
98
|
+
fetchImpl: config.fetchImpl,
|
|
99
|
+
navigate: config.navigate,
|
|
100
|
+
});
|
|
101
|
+
if (outcome.session)
|
|
102
|
+
manager.setSession(outcome.session);
|
|
103
|
+
return outcome;
|
|
104
|
+
},
|
|
105
|
+
async handleRedirectCallback(url) {
|
|
106
|
+
// Only meaningful on the web redirect path; a native target never lands here.
|
|
107
|
+
if ((0, plugins_1.isNativePlatform)({ Capacitor: plugins.Capacitor }))
|
|
108
|
+
return null;
|
|
109
|
+
const landingUrl = url ?? (typeof window !== 'undefined' ? window.location.href : undefined);
|
|
110
|
+
if (!landingUrl)
|
|
111
|
+
return null;
|
|
112
|
+
const clientId = requireString(config.clientId, 'clientId');
|
|
113
|
+
const redirectUri = requireString(config.redirectUri, 'redirectUri');
|
|
114
|
+
const session = await (0, sign_in_1.completeRedirectSignIn)({
|
|
115
|
+
frontendApi: config.frontendApi,
|
|
116
|
+
clientId,
|
|
117
|
+
redirectUri,
|
|
118
|
+
url: landingUrl,
|
|
119
|
+
pkceStore,
|
|
120
|
+
fetchImpl: config.fetchImpl,
|
|
121
|
+
});
|
|
122
|
+
if (session)
|
|
123
|
+
manager.setSession(session);
|
|
124
|
+
return session;
|
|
125
|
+
},
|
|
126
|
+
async signOut() {
|
|
127
|
+
manager.clear();
|
|
128
|
+
await (0, native_session_1.clearNativeSession)(storage);
|
|
129
|
+
},
|
|
130
|
+
getToken() {
|
|
131
|
+
return manager.getToken();
|
|
132
|
+
},
|
|
133
|
+
authHeaders() {
|
|
134
|
+
return manager.authHeaders();
|
|
135
|
+
},
|
|
136
|
+
getSession() {
|
|
137
|
+
return manager.current;
|
|
138
|
+
},
|
|
139
|
+
onChange(listener) {
|
|
140
|
+
return manager.onChange(listener);
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
// ── Re-exports: the pieces, for apps that drive the flow themselves ──────────
|
|
145
|
+
__exportStar(require("./plugins"), exports);
|
|
146
|
+
__exportStar(require("./pkce"), exports);
|
|
147
|
+
__exportStar(require("./token-store"), exports);
|
|
148
|
+
__exportStar(require("./sign-in"), exports);
|
|
149
|
+
var native_session_2 = require("./native-session");
|
|
150
|
+
Object.defineProperty(exports, "createNativeSessionManager", { enumerable: true, get: function () { return native_session_2.createNativeSessionManager; } });
|
|
151
|
+
Object.defineProperty(exports, "clearNativeSession", { enumerable: true, get: function () { return native_session_2.clearNativeSession; } });
|
|
152
|
+
Object.defineProperty(exports, "NativeSessionManager", { enumerable: true, get: function () { return native_session_2.NativeSessionManager; } });
|
|
153
|
+
Object.defineProperty(exports, "exchangeForSession", { enumerable: true, get: function () { return native_session_2.exchangeForSession; } });
|
|
154
|
+
Object.defineProperty(exports, "refreshNativeSession", { enumerable: true, get: function () { return native_session_2.refreshNativeSession; } });
|
|
155
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native session for Capacitor.
|
|
3
|
+
*
|
|
4
|
+
* A thin wiring of the framework-agnostic {@link NativeSessionManager} from
|
|
5
|
+
* `@atlasauth/js` to this package's {@link TokenStore}. The core manager owns the
|
|
6
|
+
* exchange / refresh / rotation logic; this file's only job is to PERSIST each
|
|
7
|
+
* rotated session into the store (so the rotating refresh token survives an app
|
|
8
|
+
* restart) and to rehydrate the manager from it on boot.
|
|
9
|
+
*
|
|
10
|
+
* The whole session is stored as one JSON string under the store's single slot —
|
|
11
|
+
* the refresh token (which rotates and must survive a restart) alongside the
|
|
12
|
+
* session id the refresh call needs and the current JWT. Give the native session
|
|
13
|
+
* its OWN store/key, separate from any other value the app keeps.
|
|
14
|
+
*/
|
|
15
|
+
import { NativeSessionManager } from '@atlasauth/js';
|
|
16
|
+
import { type TokenStore } from './token-store';
|
|
17
|
+
export interface NativeSessionConfig {
|
|
18
|
+
/** The instance's FAPI origin, e.g. `https://fapi.acme.atlasauth.net`. */
|
|
19
|
+
frontendApi: string;
|
|
20
|
+
/** The publishable key — sent on the refresh call and in `authHeaders()`. */
|
|
21
|
+
publishableKey: string;
|
|
22
|
+
/** The first-party OAuth client id (for a later in-manager exchange). */
|
|
23
|
+
clientId?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Where the rotated session is persisted. Defaults to a NON-persistent
|
|
26
|
+
* in-memory store — ship a `@capacitor/preferences` (or secure-storage) store
|
|
27
|
+
* (see {@link TokenStore}) in production.
|
|
28
|
+
*/
|
|
29
|
+
storage?: TokenStore;
|
|
30
|
+
/** Injectable for tests; defaults to the platform `fetch`. */
|
|
31
|
+
fetchImpl?: typeof fetch;
|
|
32
|
+
/** Injectable clock, epoch ms. Defaults to `Date.now`. */
|
|
33
|
+
now?: () => number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Build a {@link NativeSessionManager} wired to a Capacitor token store.
|
|
37
|
+
*
|
|
38
|
+
* Async because the store may be async: it reads whatever session the store
|
|
39
|
+
* holds and seeds the manager with it, so a returning user is signed in before
|
|
40
|
+
* the first request. Thereafter every rotation is written straight back to the
|
|
41
|
+
* store via the manager's `persist` hook.
|
|
42
|
+
*/
|
|
43
|
+
export declare function createNativeSessionManager(config: NativeSessionConfig): Promise<NativeSessionManager>;
|
|
44
|
+
/** Clear the persisted native session (sign-out). */
|
|
45
|
+
export declare function clearNativeSession(storage: TokenStore): Promise<void>;
|
|
46
|
+
export { NativeSessionManager, exchangeForSession, refreshNativeSession, type NativeSession, } from '@atlasauth/js';
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Native session for Capacitor.
|
|
4
|
+
*
|
|
5
|
+
* A thin wiring of the framework-agnostic {@link NativeSessionManager} from
|
|
6
|
+
* `@atlasauth/js` to this package's {@link TokenStore}. The core manager owns the
|
|
7
|
+
* exchange / refresh / rotation logic; this file's only job is to PERSIST each
|
|
8
|
+
* rotated session into the store (so the rotating refresh token survives an app
|
|
9
|
+
* restart) and to rehydrate the manager from it on boot.
|
|
10
|
+
*
|
|
11
|
+
* The whole session is stored as one JSON string under the store's single slot —
|
|
12
|
+
* the refresh token (which rotates and must survive a restart) alongside the
|
|
13
|
+
* session id the refresh call needs and the current JWT. Give the native session
|
|
14
|
+
* its OWN store/key, separate from any other value the app keeps.
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.refreshNativeSession = exports.exchangeForSession = exports.NativeSessionManager = void 0;
|
|
18
|
+
exports.createNativeSessionManager = createNativeSessionManager;
|
|
19
|
+
exports.clearNativeSession = clearNativeSession;
|
|
20
|
+
const js_1 = require("@atlasauth/js");
|
|
21
|
+
const token_store_1 = require("./token-store");
|
|
22
|
+
/**
|
|
23
|
+
* Build a {@link NativeSessionManager} wired to a Capacitor token store.
|
|
24
|
+
*
|
|
25
|
+
* Async because the store may be async: it reads whatever session the store
|
|
26
|
+
* holds and seeds the manager with it, so a returning user is signed in before
|
|
27
|
+
* the first request. Thereafter every rotation is written straight back to the
|
|
28
|
+
* store via the manager's `persist` hook.
|
|
29
|
+
*/
|
|
30
|
+
async function createNativeSessionManager(config) {
|
|
31
|
+
const storage = config.storage ?? (0, token_store_1.createInMemoryTokenStore)();
|
|
32
|
+
const initial = (0, js_1.parseNativeSession)(await storage.getToken()) ?? undefined;
|
|
33
|
+
return new js_1.NativeSessionManager({
|
|
34
|
+
baseUrl: config.frontendApi,
|
|
35
|
+
publishableKey: config.publishableKey,
|
|
36
|
+
clientId: config.clientId,
|
|
37
|
+
initial,
|
|
38
|
+
fetchImpl: config.fetchImpl,
|
|
39
|
+
now: config.now,
|
|
40
|
+
// The manager calls this on every set/rotate; persist the fresh session so
|
|
41
|
+
// the rotated refresh token survives an app restart. Fire-and-forget — the
|
|
42
|
+
// store may be async, and a write failure must not break the live session.
|
|
43
|
+
persist: (session) => {
|
|
44
|
+
void Promise.resolve(storage.setToken((0, js_1.serializeNativeSession)(session))).catch(() => undefined);
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
/** Clear the persisted native session (sign-out). */
|
|
49
|
+
async function clearNativeSession(storage) {
|
|
50
|
+
await storage.clearToken();
|
|
51
|
+
}
|
|
52
|
+
var js_2 = require("@atlasauth/js");
|
|
53
|
+
Object.defineProperty(exports, "NativeSessionManager", { enumerable: true, get: function () { return js_2.NativeSessionManager; } });
|
|
54
|
+
Object.defineProperty(exports, "exchangeForSession", { enumerable: true, get: function () { return js_2.exchangeForSession; } });
|
|
55
|
+
Object.defineProperty(exports, "refreshNativeSession", { enumerable: true, get: function () { return js_2.refreshNativeSession; } });
|
|
56
|
+
//# sourceMappingURL=native-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-session.js","sourceRoot":"","sources":["../src/native-session.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG;;;AAqCH,gEAsBC;AAGD,gDAEC;AA9DD,sCAKuB;AACvB,+CAA0E;AAqB1E;;;;;;;GAOG;AACI,KAAK,UAAU,0BAA0B,CAC9C,MAA2B;IAE3B,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,IAAA,sCAAwB,GAAE,CAAC;IAC7D,MAAM,OAAO,GAAG,IAAA,uBAAkB,EAAC,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC,IAAI,SAAS,CAAC;IAE1E,OAAO,IAAI,yBAAoB,CAAC;QAC9B,OAAO,EAAE,MAAM,CAAC,WAAW;QAC3B,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,OAAO;QACP,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,2EAA2E;QAC3E,2EAA2E;QAC3E,2EAA2E;QAC3E,OAAO,EAAE,CAAC,OAAsB,EAAE,EAAE;YAClC,KAAK,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAA,2BAAsB,EAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAC3E,GAAG,EAAE,CAAC,SAAS,CAChB,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,qDAAqD;AAC9C,KAAK,UAAU,kBAAkB,CAAC,OAAmB;IAC1D,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC;AAC7B,CAAC;AAED,oCAKuB;AAJrB,0GAAA,oBAAoB,OAAA;AACpB,wGAAA,kBAAkB,OAAA;AAClB,0GAAA,oBAAoB,OAAA"}
|
package/dist/pkce.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PKCE (RFC 7636, S256) for the native authorization-code flow.
|
|
3
|
+
*
|
|
4
|
+
* A first-party native/Capacitor client is a PUBLIC client — it ships no secret
|
|
5
|
+
* — so it proves possession of its own authorization request with PKCE: it keeps
|
|
6
|
+
* a random `verifier`, sends only `code_challenge = base64url(SHA-256(verifier))`
|
|
7
|
+
* on the authorize URL, and presents the `verifier` when it redeems the code. A
|
|
8
|
+
* code intercepted on the deep-link callback is inert without the verifier, which
|
|
9
|
+
* never leaves the app.
|
|
10
|
+
*
|
|
11
|
+
* Uses only Web Crypto globals (`crypto.getRandomValues`, `crypto.subtle`), which
|
|
12
|
+
* every Capacitor target provides — the iOS/Android system WebView and the web
|
|
13
|
+
* build alike — so there is no `node:crypto` import. Mirrors `createPkcePair`
|
|
14
|
+
* from `@atlasauth/backend`'s handshake, here on the client side of the exchange.
|
|
15
|
+
*/
|
|
16
|
+
export interface PkcePair {
|
|
17
|
+
/** Kept in the app; presented only when the code is redeemed, never on the URL. */
|
|
18
|
+
verifier: string;
|
|
19
|
+
/** base64url(SHA-256(verifier)); the only half that rides the authorize URL. */
|
|
20
|
+
challenge: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Generate a PKCE S256 pair. The verifier is 32 random bytes, base64url-encoded
|
|
24
|
+
* (43 chars — within RFC 7636's 43–128 range); the challenge is its SHA-256
|
|
25
|
+
* digest, base64url-encoded.
|
|
26
|
+
*/
|
|
27
|
+
export declare function createPkcePair(): Promise<PkcePair>;
|
|
28
|
+
/**
|
|
29
|
+
* Mint a random `state` value for CSRF binding of the authorize request. Sent on
|
|
30
|
+
* the authorize URL and checked against the value echoed back on the deep-link
|
|
31
|
+
* callback, so an unsolicited callback (a deep link we did not initiate) is
|
|
32
|
+
* rejected.
|
|
33
|
+
*/
|
|
34
|
+
export declare function createState(): string;
|
package/dist/pkce.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* PKCE (RFC 7636, S256) for the native authorization-code flow.
|
|
4
|
+
*
|
|
5
|
+
* A first-party native/Capacitor client is a PUBLIC client — it ships no secret
|
|
6
|
+
* — so it proves possession of its own authorization request with PKCE: it keeps
|
|
7
|
+
* a random `verifier`, sends only `code_challenge = base64url(SHA-256(verifier))`
|
|
8
|
+
* on the authorize URL, and presents the `verifier` when it redeems the code. A
|
|
9
|
+
* code intercepted on the deep-link callback is inert without the verifier, which
|
|
10
|
+
* never leaves the app.
|
|
11
|
+
*
|
|
12
|
+
* Uses only Web Crypto globals (`crypto.getRandomValues`, `crypto.subtle`), which
|
|
13
|
+
* every Capacitor target provides — the iOS/Android system WebView and the web
|
|
14
|
+
* build alike — so there is no `node:crypto` import. Mirrors `createPkcePair`
|
|
15
|
+
* from `@atlasauth/backend`'s handshake, here on the client side of the exchange.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.createPkcePair = createPkcePair;
|
|
19
|
+
exports.createState = createState;
|
|
20
|
+
/** base64url, no padding — the encoding PKCE and OAuth use for these values. */
|
|
21
|
+
function base64url(bytes) {
|
|
22
|
+
let bin = '';
|
|
23
|
+
for (const b of bytes)
|
|
24
|
+
bin += String.fromCharCode(b);
|
|
25
|
+
return btoa(bin).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Generate a PKCE S256 pair. The verifier is 32 random bytes, base64url-encoded
|
|
29
|
+
* (43 chars — within RFC 7636's 43–128 range); the challenge is its SHA-256
|
|
30
|
+
* digest, base64url-encoded.
|
|
31
|
+
*/
|
|
32
|
+
async function createPkcePair() {
|
|
33
|
+
const raw = new Uint8Array(32);
|
|
34
|
+
crypto.getRandomValues(raw);
|
|
35
|
+
const verifier = base64url(raw);
|
|
36
|
+
const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier));
|
|
37
|
+
return { verifier, challenge: base64url(new Uint8Array(digest)) };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Mint a random `state` value for CSRF binding of the authorize request. Sent on
|
|
41
|
+
* the authorize URL and checked against the value echoed back on the deep-link
|
|
42
|
+
* callback, so an unsolicited callback (a deep link we did not initiate) is
|
|
43
|
+
* rejected.
|
|
44
|
+
*/
|
|
45
|
+
function createState() {
|
|
46
|
+
const raw = new Uint8Array(16);
|
|
47
|
+
crypto.getRandomValues(raw);
|
|
48
|
+
return base64url(raw);
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=pkce.js.map
|
package/dist/pkce.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pkce.js","sourceRoot":"","sources":["../src/pkce.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;AAqBH,wCAMC;AAQD,kCAIC;AArCD,gFAAgF;AAChF,SAAS,SAAS,CAAC,KAAiB;IAClC,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,GAAG,IAAI,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACrD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAC9E,CAAC;AASD;;;;GAIG;AACI,KAAK,UAAU,cAAc;IAClC,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IAC/B,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;IAC5B,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;IACzF,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;AACpE,CAAC;AAED;;;;;GAKG;AACH,SAAgB,WAAW;IACzB,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IAC/B,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;IAC5B,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC;AACxB,CAAC"}
|