@tensorgrad/oauth 0.1.1 → 0.2.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 +17 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@ Small OAuth client SDK for integrating tensorGrad SSO into first-party apps.
|
|
|
7
7
|
- creates `state` values
|
|
8
8
|
- creates PKCE verifier/challenge pairs
|
|
9
9
|
- builds tensorGrad `/oauth/authorize` URLs
|
|
10
|
+
- supports `prompt=login` for account switching
|
|
10
11
|
- exchanges authorization codes at `/oauth/token`
|
|
11
12
|
- fetches canonical identity from `/oauth/userinfo`
|
|
12
13
|
- normalizes tensorGrad user payloads
|
|
@@ -100,9 +101,21 @@ export default {
|
|
|
100
101
|
}
|
|
101
102
|
|
|
102
103
|
if (url.pathname === "/auth/callback") {
|
|
104
|
+
const oauthError = url.searchParams.get("error");
|
|
105
|
+
const oauthErrorDescription = url.searchParams.get("error_description");
|
|
103
106
|
const code = url.searchParams.get("code");
|
|
104
107
|
const state = url.searchParams.get("state");
|
|
105
108
|
|
|
109
|
+
if (oauthError) {
|
|
110
|
+
return Response.json(
|
|
111
|
+
{
|
|
112
|
+
error: oauthError,
|
|
113
|
+
errorDescription: oauthErrorDescription ?? null
|
|
114
|
+
},
|
|
115
|
+
{ status: 400 }
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
106
119
|
if (!code || !state) {
|
|
107
120
|
return new Response("Missing code or state", { status: 400 });
|
|
108
121
|
}
|
|
@@ -113,6 +126,7 @@ export default {
|
|
|
113
126
|
const expectedState = "<persisted-state>";
|
|
114
127
|
const codeVerifier = "<persisted-code-verifier>";
|
|
115
128
|
|
|
129
|
+
// Use a constant-time comparison in your app when comparing secrets.
|
|
116
130
|
if (state !== expectedState) {
|
|
117
131
|
return new Response("Invalid state", { status: 400 });
|
|
118
132
|
}
|
|
@@ -152,5 +166,8 @@ export default {
|
|
|
152
166
|
- tensorGrad currently uses `https://www.tensorgrad.com` as the OAuth provider.
|
|
153
167
|
- `DEFAULT_TG_SCOPES` is the recommended scope set for first-party apps.
|
|
154
168
|
- `assertGrantedScopes(token.scope, ["admin"])` is the simplest way to require admin access.
|
|
169
|
+
- pass `prompt: "login"` to `createAuthorizationUrl(...)` when you need tensorGrad to force a fresh account selection.
|
|
170
|
+
- handle `error` / `error_description` on the callback before validating `code`
|
|
171
|
+
- compare persisted `state` values using a constant-time comparison in your app
|
|
155
172
|
- `isAdminScopeGranted(token.scope)` is available when you only need a boolean check.
|
|
156
173
|
- app session and logout handling stay in the consuming app.
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -90,6 +90,9 @@ export function createAuthorizationUrl(config, options) {
|
|
|
90
90
|
url.searchParams.set("response_type", "code");
|
|
91
91
|
url.searchParams.set("scope", scope);
|
|
92
92
|
url.searchParams.set("state", state);
|
|
93
|
+
if (options.prompt) {
|
|
94
|
+
url.searchParams.set("prompt", options.prompt);
|
|
95
|
+
}
|
|
93
96
|
if (options.codeChallenge) {
|
|
94
97
|
url.searchParams.set("code_challenge", requireNonEmptyString("codeChallenge", options.codeChallenge));
|
|
95
98
|
url.searchParams.set("code_challenge_method", options.codeChallengeMethod ?? "S256");
|