如何配置OAuth2令牌请求?求OAuth/WebAPI跨应用隔离登录最佳实践
Hey there, let’s walk through how to properly separate your B2C (App A: https://example.com) and B2B (App B: https://admin.example.com) user pools while sharing the same token endpoint (https://api.domain.com/oauth/token). Since both are pure Angular SPAs with no backend, we’ll focus on OAuth 2.0 configuration and API-level enforcement to keep users fully isolated.
Core Strategies for Isolation
1. Use Distinct OAuth Client IDs
First, register two unique client IDs with your authorization server (the service behind /oauth/token):
- One dedicated to App A (for B2C end customers)
- Another exclusively for App B (for B2B partners)
When each app initiates a token request, it must send its specific client_id (and leverage PKCE—more on that below—since SPAs can’t safely store client secrets). Your auth server should be configured to link each client ID to its respective user pool, ensuring tokens issued for App A can only be associated with B2C users, and vice versa.
2. Segregate User Pools at the Auth Server
Create two separate logical user groups (or databases) in your authorization server:
- A
b2c_customersgroup for App A’s end users - A
b2b_partnersgroup for App B’s partner users
When a user signs up via App A, automatically assign them to the b2c_customers group; do the same for App B users and the b2b_partners group. Add server-side rules to block cross-group access—for example, if a B2B user tries to log in using App A’s client ID, the auth server should immediately reject the request.
3. Enforce Claims in Access Tokens
Configure your auth server to include custom claims in every access token to enforce isolation:
- A
user_poolclaim (e.g.,"user_pool": "b2c"or"user_pool": "b2b") that clearly identifies which group the user belongs to - The standard
azp(authorized party) claim, which will match the app’s client ID
In your Web API (C), add middleware to validate these claims on every request. Here’s a quick example for a Node.js/Express API:
// Middleware to validate user pool and client ID match const validateUserPool = (req, res, next) => { const { user_pool, azp } = req.user.claims; const appAClientId = "your-app-a-client-id"; const appBClientId = "your-app-b-client-id"; if ((azp === appAClientId && user_pool !== "b2c") || (azp === appBClientId && user_pool !== "b2b")) { return res.status(403).json({ message: "User pool mismatch for this application" }); } next(); }; // Apply validation to all API routes app.use("/api", validateUserPool);
4. Use PKCE for Secure Token Flows
Since both apps are pure SPAs (public clients), avoid Implicit Flow or Resource Owner Password Flow—instead, use the Authorization Code Flow with PKCE (Proof Key for Code Exchange). This is the industry standard for SPAs because it eliminates the need to store client secrets and prevents authorization code interception attacks.
For each login attempt:
- The app generates a random
code_verifierand its SHA-256 hash (code_challenge) - The
code_challengeis sent to the auth server during the authorization request - When exchanging the authorization code for a token, the app sends the
code_verifierto prove it’s the same client that initiated the request
Make sure your /oauth/token endpoint is configured to support PKCE validation.
5. Isolate Sign-Up Flows
Even though both apps use the same token endpoint, build separate sign-up UIs in App A and App B. When sending sign-up requests to the auth server, include a user_type parameter (e.g., customer or partner) to tell the server which pool to assign the user to. Add server-side validation to reject sign-up requests that don’t include this parameter or send a value mismatched with the client ID.
Bonus Security Tips
- Short-lived tokens: Use access tokens that expire in 15-30 minutes, paired with refresh tokens that rotate on each use to limit the impact of leaks.
- CORS restrictions: Configure your Web API (C) to only allow requests from
https://example.comandhttps://admin.example.com. - Rate limiting: Add rate limits to the
/oauth/tokenendpoint to prevent brute-force attacks on user credentials.
内容的提问来源于stack exchange,提问作者igby

