@hyper.authio/client 0.8.1 → 0.10.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 +6 -1
- package/dist/index.cjs +26 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +45 -3
- package/dist/index.d.ts +45 -3
- package/dist/index.js +25 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -102,6 +102,11 @@ callback that is not for the transaction throws `AuthioCallbackError` (`reason`:
|
|
|
102
102
|
`missing_issuer`, `missing_code`); an OAuth error Authio sent back (`login_required` after `prompt: "none"`, for one)
|
|
103
103
|
throws `AuthioProtocolError`.
|
|
104
104
|
|
|
105
|
+
`acrValues` asks for a sign-in level; it does not guarantee one. Authio may sign the person in with less (no second
|
|
106
|
+
factor enrolled and none required by the client), as OpenID Connect allows (`acr_values` is a voluntary claim), so
|
|
107
|
+
read `idToken.acr` after the callback and refuse a sign-in below the level the app needs, as
|
|
108
|
+
[`examples/web-login`](../../examples/web-login/server.mjs) does.
|
|
109
|
+
|
|
105
110
|
### ID tokens and sign-out
|
|
106
111
|
|
|
107
112
|
```ts
|
|
@@ -238,7 +243,7 @@ const user = asUserEvent(event); // { id, username, emailConfirmed, … } for us
|
|
|
238
243
|
|
|
239
244
|
Every event type has its accessor (`asLoginEvent`, `asUserLockedOutEvent`, `asTokenRevokedEvent`,
|
|
240
245
|
`asKeysRotatedEvent`, `asTokenReuseDetectedEvent`, `asAdminResourceEvent`, `asUserSuspensionEvent`,
|
|
241
|
-
`asAttackDetectedEvent`, `asCredentialCompromisedEvent`, `asPingEvent`), which exposes every member of `data` in
|
|
246
|
+
`asAttackDetectedEvent`, `asCredentialCompromisedEvent`, `asAuthenticatorAppEvent`, `asPingEvent`), which exposes every member of `data` in
|
|
242
247
|
camelCase with its value unchanged; `event.data` stays as delivered (snake_case). An unknown type still parses
|
|
243
248
|
(`isKnownWebhookEventType` is `false`, `event.data` is the raw JSON).
|
|
244
249
|
|
package/dist/index.cjs
CHANGED
|
@@ -129,6 +129,10 @@ var AuthioWebhookEventTypes = {
|
|
|
129
129
|
UserSuspensionEnded: "user_suspension_ended",
|
|
130
130
|
AttackDetected: "attack_detected",
|
|
131
131
|
CredentialCompromised: "credential_compromised",
|
|
132
|
+
UserAuthenticatorAppEnrolled: "user_authenticator_app_enrolled",
|
|
133
|
+
UserAuthenticatorAppRemoved: "user_authenticator_app_removed",
|
|
134
|
+
UserRecoveryCodesRegenerated: "user_recovery_codes_regenerated",
|
|
135
|
+
UserRecoveryCodeUsed: "user_recovery_code_used",
|
|
132
136
|
Ping: "ping"
|
|
133
137
|
};
|
|
134
138
|
var AuthioWebhookHeaders = {
|
|
@@ -164,6 +168,8 @@ var AuthioDefaults = {
|
|
|
164
168
|
CredentialClientIdPrefix: "cred_",
|
|
165
169
|
ApiKeyHeader: "x-api-key",
|
|
166
170
|
RequestIdHeader: "X-Request-Id",
|
|
171
|
+
/** The header `typ` of an access token (RFC 9068 §2.1). */
|
|
172
|
+
AccessTokenType: "at+jwt",
|
|
167
173
|
/** The header `typ` of a back-channel logout token. */
|
|
168
174
|
LogoutTokenType: "logout+jwt",
|
|
169
175
|
/** The event a back-channel logout token carries. */
|
|
@@ -962,6 +968,14 @@ async function validateAuthioIdToken(token, context, expectations = {}) {
|
|
|
962
968
|
}
|
|
963
969
|
return payload;
|
|
964
970
|
}
|
|
971
|
+
function requireAccessTokenType(header) {
|
|
972
|
+
const type = typeof header.typ === "string" ? header.typ.toLowerCase() : void 0;
|
|
973
|
+
if (type !== AuthioDefaults.AccessTokenType && type !== `application/${AuthioDefaults.AccessTokenType}`)
|
|
974
|
+
throw new AuthioTokenValidationError(
|
|
975
|
+
"not_access_token",
|
|
976
|
+
`Only access tokens are accepted; this token's header typ is '${header.typ ?? ""}', not '${AuthioDefaults.AccessTokenType}'.`
|
|
977
|
+
);
|
|
978
|
+
}
|
|
965
979
|
async function validateAuthioLogoutToken(token, context) {
|
|
966
980
|
const signed = isAuthioTokenEncrypted(token) ? await context.decrypt(token) : token;
|
|
967
981
|
const invalid = (message) => new AuthioTokenValidationError("invalid_logout_token", message);
|
|
@@ -1293,12 +1307,13 @@ function createAuthioClient(options) {
|
|
|
1293
1307
|
const signed = await decrypt(accessToken);
|
|
1294
1308
|
if (signed.split(".").length !== 3) return void 0;
|
|
1295
1309
|
const document = await discovery.get(callOptions.signal);
|
|
1296
|
-
const { payload } = await verifyAuthioJwt(signed, withClientSecret(await signingKeys(callOptions.signal), clientSecret), {
|
|
1310
|
+
const { payload, header } = await verifyAuthioJwt(signed, withClientSecret(await signingKeys(callOptions.signal), clientSecret), {
|
|
1297
1311
|
issuer: connection.issuer,
|
|
1298
1312
|
algorithms: acceptedSigningAlgorithms(accessTokenAlgorithm, document.id_token_signing_alg_values_supported),
|
|
1299
1313
|
clockSkew,
|
|
1300
1314
|
now: connection.clock.now()
|
|
1301
1315
|
});
|
|
1316
|
+
requireAccessTokenType(header);
|
|
1302
1317
|
return payload;
|
|
1303
1318
|
},
|
|
1304
1319
|
async createEndSessionUrl(request = {}) {
|
|
@@ -1711,7 +1726,7 @@ function createAuthioAccountCredential(options) {
|
|
|
1711
1726
|
if (cached && clock.now() < cached.refreshAt) return cached;
|
|
1712
1727
|
pending ??= (async () => {
|
|
1713
1728
|
const issuedAt = clock.now();
|
|
1714
|
-
const answer = kind === "client_secret" ? await client.tokens.clientCredentials({ scopes: scope, signal }) : await client.tokens.personalAccessToken({ token: value, scopes: scope, signal });
|
|
1729
|
+
const answer = kind === "client_secret" ? await client.tokens.clientCredentials({ scopes: scope, signal }) : await client.tokens.personalAccessToken({ token: value, clientId: AuthioDefaults.PlatformClientId, scopes: scope, signal });
|
|
1715
1730
|
cached = toClientCredentialsToken(answer, issuedAt, refreshSkewMs);
|
|
1716
1731
|
return cached;
|
|
1717
1732
|
})().finally(() => {
|
|
@@ -2024,6 +2039,13 @@ var asAdminResourceEvent = (event) => dataWhen(
|
|
|
2024
2039
|
var asUserSuspensionEvent = (event) => dataWhen(event, AuthioWebhookEventTypes.UserSuspended, AuthioWebhookEventTypes.UserSuspensionEnded);
|
|
2025
2040
|
var asAttackDetectedEvent = (event) => dataWhen(event, AuthioWebhookEventTypes.AttackDetected);
|
|
2026
2041
|
var asCredentialCompromisedEvent = (event) => dataWhen(event, AuthioWebhookEventTypes.CredentialCompromised);
|
|
2042
|
+
var asAuthenticatorAppEvent = (event) => dataWhen(
|
|
2043
|
+
event,
|
|
2044
|
+
AuthioWebhookEventTypes.UserAuthenticatorAppEnrolled,
|
|
2045
|
+
AuthioWebhookEventTypes.UserAuthenticatorAppRemoved,
|
|
2046
|
+
AuthioWebhookEventTypes.UserRecoveryCodesRegenerated,
|
|
2047
|
+
AuthioWebhookEventTypes.UserRecoveryCodeUsed
|
|
2048
|
+
);
|
|
2027
2049
|
var asPingEvent = (event) => dataWhen(event, AuthioWebhookEventTypes.Ping);
|
|
2028
2050
|
var knownEventTypes = new Set(Object.values(AuthioWebhookEventTypes));
|
|
2029
2051
|
function isKnownWebhookEventType(type) {
|
|
@@ -2108,6 +2130,7 @@ exports.AuthioWebhookEventTypes = AuthioWebhookEventTypes;
|
|
|
2108
2130
|
exports.AuthioWebhookHeaders = AuthioWebhookHeaders;
|
|
2109
2131
|
exports.asAdminResourceEvent = asAdminResourceEvent;
|
|
2110
2132
|
exports.asAttackDetectedEvent = asAttackDetectedEvent;
|
|
2133
|
+
exports.asAuthenticatorAppEvent = asAuthenticatorAppEvent;
|
|
2111
2134
|
exports.asCredentialCompromisedEvent = asCredentialCompromisedEvent;
|
|
2112
2135
|
exports.asKeysRotatedEvent = asKeysRotatedEvent;
|
|
2113
2136
|
exports.asLoginEvent = asLoginEvent;
|
|
@@ -2140,6 +2163,7 @@ exports.randomValue = randomValue;
|
|
|
2140
2163
|
exports.readAuthioAdminResponse = readAuthioAdminResponse;
|
|
2141
2164
|
exports.readAuthioFrontChannelLogout = readAuthioFrontChannelLogout;
|
|
2142
2165
|
exports.readWebhookEventData = readWebhookEventData;
|
|
2166
|
+
exports.requireAccessTokenType = requireAccessTokenType;
|
|
2143
2167
|
exports.requireHmacSecretLength = requireHmacSecretLength;
|
|
2144
2168
|
exports.resolveConnection = resolveConnection;
|
|
2145
2169
|
exports.resolveIssuer = resolveIssuer;
|