0
LiSong created
I have implemented SSO in a Next.js site using ABP.io, but when I call the API endpoints, I get a 401. Is there any doc on how to call an endpoint with the SSO token? thanks
2 Answer(s)
-
0
- Solution
What’s happening:
- In an ABP solution with MVC UI (cookies as the default auth scheme), API endpoints challenge unauthenticated requests with a redirect to the login page. A non-browser client (like your Next.js app) must call those endpoints with a valid Bearer access token obtained from your SSO provider (OpenIddict/IdentityServer in ABP). If the request has no Bearer token (or the API is not configured to accept it), you’ll see 401 or an HTML login response.
End-to-end steps to call protected APIs from your Next.js app using the SSO token:
- Ensure your backend accepts JWT Bearer tokens on the API
- In your HttpApi.Host module, configure JWT bearer authentication. ABP templates already do this, but verify that the AddJwtBearer config is present and the API resource scopes include your application’s scope.
- If your Next.js app will access the backend from a different origin, add that origin to CORS.
- Register your Next.js client in IdentityServer/OpenIddict
- Add a public SPA client using the authorization_code flow with PKCE, redirect URIs for your Next.js app, and proper CORS origins. This is done in IdentityServerDataSeedContributor (or OpenIddict seed) and appsettings (DbMigrator).
- Typical settings:
- Grant types: authorization_code
- RequireClientSecret: false
- RedirectUris: https://your-next-app.com/callback
- PostLogoutRedirectUris: https://your-next-app.com
- AllowedCorsOrigins: https://your-next-app.com
- Scopes: openid profile email role phone address and your API scope (e.g., YourAppName)
- Add offline_access if you need refresh tokens.
- Authenticate in Next.js and get the access token
- Use an OIDC library that supports Code + PKCE in Next.js (e.g., next-auth with an OIDC provider, or a low-level OIDC client). After the callback completes, you will have an access_token.
- Attach the access token to API requests
- From Next.js (on the server or client), include: Authorization: Bearer {access_token}
- Example with fetch:
const res = await fetch(
${process.env.NEXT_PUBLIC_API_URL}/api/identity/my-profile, { headers: { Authorization:Bearer ${accessToken}, 'Accept-Language': 'en', // optional 'Abp-TenantId': tenantId ?? '' // if you use multi-tenancy and need to target a tenant } }); if (res.status === 401) { // handle re-auth or token refresh }
- Handle 401 vs. login redirects
- Cookies scheme redirects to login for browser requests. When calling from your Next.js code via fetch/axios with Bearer tokens, you’ll see 401 on invalid/expired tokens (not the HTML login) as long as you don’t rely on cookie auth for those calls.
- If you still get redirected HTML, ensure:
- You are not sending the MVC cookie along with the API call.
- You are targeting the HttpApi.Host URL (not the MVC UI host’s MVC action).
- The request has a Bearer token and the API pipeline has JWT bearer enabled.
- Validate issuer when using tunnels/custom domains
- If the Issuer differs from the Authority (e.g., ngrok/public URL), add ValidIssuers to AuthServer settings and configure TokenValidationParameters.ValidIssuers accordingly.
- Common pitfalls that cause 401:
- Missing API scope in the requested scopes of the Next.js client.
- Wrong authority/issuer in Next.js OIDC config.
- CORS not allowing your Next.js origin.
- Access token expired and no refresh handling.
Minimal code example (server-side Next.js API route proxying to ABP API):
// /pages/api/me.ts import type { NextApiRequest, NextApiResponse } from 'next'; export default async function handler(req: NextApiRequest, res: NextApiResponse) { const accessToken = req.headers['authorization']?.toString().replace(/^Bearer\s+/i, ''); if (!accessToken) { return res.status(401).json({ error: 'No access token' }); } const apiUrl = process.env.NEXT_PUBLIC_API_URL; // e.g. https://localhost:44350 const r = await fetch(`${apiUrl}/api/identity/my-profile`, { headers: { Authorization: `Bearer ${accessToken}` } }); if (!r.ok) { return res.status(r.status).send(await r.text()); } return res.status(200).json(await r.json()); }- Sources
- Support discussion about 401 vs login redirects and how API calls should use Authorization: Bearer:
- https://abp.io/support/questions/611
- Support discussion on 401 vs redirect behaviors in MVC and how requests differ:
- https://abp.io/support/questions/3281
- Community example showing attaching Bearer token and calling /api/identity/users:
- https://abp.io/community/articles/aqjjwsdf
- Community example showing getting tokens and posting to /connect/token (for reference on scopes/flows):
- https://abp.io/community/articles/e74fmblw
This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.
-
0
hi
Where is the token you're getting from? AuthServer?
What are the details of the 401 logs? See debug logs.
https://abp.io/support/questions/8622/How-to-enable-Debug-logs-for-troubleshoot-problems
Thanks.