|
| 1 | +/** |
| 2 | + * Dev-only OIDC provider for local testing. |
| 3 | + * |
| 4 | + * IMPORTANT: This is NOT for production use. It: |
| 5 | + * - Auto logs-in a test user and auto-consents |
| 6 | + * - Issues refresh tokens unconditionally (issueRefreshToken = true) |
| 7 | + * - Uses very short AccessToken TTL (15s) to exercise refresh flow |
| 8 | + * - Uses in-memory adapter and generated signing keys |
| 9 | + */ |
1 | 10 | import { config } from "dotenv"; |
2 | 11 | import Provider from "oidc-provider"; |
3 | 12 |
|
@@ -65,16 +74,24 @@ const configuration = { |
65 | 74 | }, |
66 | 75 | }, |
67 | 76 | features: { |
68 | | - devInteractions: { enabled: true }, // Enable dev interactions for easy testing |
| 77 | + // Disable built-in dev interactions in favor of our custom auto-login |
| 78 | + // and auto-consent middleware used for local testing. |
| 79 | + devInteractions: { enabled: false }, |
69 | 80 | }, |
| 81 | + // Explicitly declare supported scopes, including offline_access for refresh tokens |
| 82 | + // Scopes supported by the dev provider (app requests offline_access in dev and prod) |
| 83 | + scopes: ["openid", "email", "profile", "offline_access"], |
70 | 84 | claims: { |
71 | 85 | email: ["email", "email_verified"], |
72 | 86 | profile: ["name"], |
73 | 87 | }, |
74 | 88 | ttl: { |
75 | | - AccessToken: 3600, // 1 hour |
| 89 | + // Short-lived access tokens to force refresh during dev |
| 90 | + AccessToken: 15, // seconds |
76 | 91 | RefreshToken: 86400 * 30, // 30 days |
77 | 92 | }, |
| 93 | + // Dev-only: always issue refresh tokens to make the flow reliable locally |
| 94 | + issueRefreshToken: async () => true, |
78 | 95 | }; |
79 | 96 |
|
80 | 97 | const oidc = new Provider(ISSUER, configuration); |
@@ -107,12 +124,17 @@ oidc.use(async (ctx, next) => { |
107 | 124 | clientId: interaction.params.client_id, |
108 | 125 | }); |
109 | 126 |
|
110 | | - grant.addOIDCScope( |
111 | | - interaction.params.scope |
112 | | - ?.split(" ") |
113 | | - .filter((scope) => ["openid", "email", "profile"].includes(scope)) |
114 | | - .join(" ") || "openid email profile", |
| 127 | + // Grant requested scopes intersected with allowed ones |
| 128 | + const requestedScopes = interaction.params.scope |
| 129 | + ?.split(" ") |
| 130 | + .filter(Boolean) || ["openid", "email", "profile"]; |
| 131 | + const allowedScopes = ["openid", "email", "profile", "offline_access"]; |
| 132 | + const grantedScopes = requestedScopes.filter((s) => |
| 133 | + allowedScopes.includes(s), |
115 | 134 | ); |
| 135 | + // Dev-only provider already issues refresh tokens unconditionally via |
| 136 | + // `issueRefreshToken`, so we don't need to force-add offline_access here. |
| 137 | + grant.addOIDCScope(grantedScopes.join(" ")); |
116 | 138 |
|
117 | 139 | await grant.save(); |
118 | 140 |
|
|
0 commit comments