Next-auth - unable to redirect to specific url after successful login/logout (keycloak provider) - next.js

I have a two basic next apps that uses next-auth for its authentication along with keycloak provider.
i've been trying to use the feature of SSO (single sign on) that keyckoak provides, so i have a website running on http://localhost:3000/ and another one on http://localhost:3001/, and everytime i try to login using the second app, it redirects me to localhost 3000, not localhost 3001, which is a weird behavior, let me show you some code.
api/auth/[...nextauth].ts
(note: i'm using same realm and clientId for both apps)
import NextAuth from "next-auth/next";
import KeycloackProvider from "next-auth/providers/keycloak";
export default NextAuth({
debug: true,
providers: [
KeycloackProvider({
clientId: "react-client-1",
clientSecret: "react-auth",
issuer: "http://localhost:8080/realms/react-auth",
enter image description here }),
],
});
Function to sign in
here, the callbackUrl just doesn't work, no matter what i put there, it's just not going to redirect me to that url
const handleKeycloackSignIn = (): void => {
signIn("keycloak", {
callbackUrl: "http://localhost:3001/",
});
};
next-auth cookies for redirecting on localhost:3001
photo #1
Keycloack config
photo #2
What could be the reason for always redirecting to localhost:3000 ? is it some next-auth config that i'm missing or, maybe is related to keycloak ?
How can i redirect to wherever i want after a successful login/logout
I've tried hardcore google search around this topic, nothing really related to my specific issue.

You need to add some variables that next-auth need to your .env file, something like this.
NEXTAUTH_URL=http://localhost:3000/
NEXTAUTH_SECRET=PRUEBA
this provides the url to redirect and a secret to your jwt token

Related

Confirmation of why cross-origin problems occur when using signInWithRedirect are resolved

I know that the signInWithRedirect() flow in Firebase does not behave correctly in some browsers because it uses cross-origin.
https://github.com/firebase/firebase-js-sdk/issues/6716
When using signInWithRedirect(), the following article is a best practice.
https://firebase.google.com/docs/auth/web/redirect-best-practices
I have an app created in Next.js with authentication using signInWithRedirect() and deployed it to Vercel.
If I do nothing, it will not work in Safari as described in the above issue.
So I took the following 3 actions and confirmed that it works correctly.
Reverse proxy settings(next.config.js)
/** #type {import('next').NextConfig} */
module.exports = {
reactStrictMode: true,
async rewrites() {
return [
{
source: '/__/auth/:path*',
destination: `https://${process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN}/__/auth/:path*`,
},
]
},
}
Changed authDomain when initializing FirebaseApp to the app's domain
In GCP, change approved redirect URI to https://<the-domain-that-serves-my-app>/__/auth/handler.
These are the third method in Best practices.
I do not fully understand why this setup solves the problem, and I would like to correct my understanding.
My understanding is as follows
authDomain = a.com (domain of the app)
An authentication request is generated from the browser and redirected to authDomain (a.com)
The request is forwarded to https://<project>.firebaseapp.com/__/auth/ because a reverse proxy is set up
Host the login helper code to the identity provider at <project>.firebaseapp.com.
Return to a.com
Access login helper storage from browser
Authenticated redirect URI is set to the app domain, so the information is stored in the browser's storage in the app domain. And since the authDomain is the same as the app's, the authentication iFrame is referenced to it.
Is this understanding correct?

Firebase 3rd-party AuthProvider (Google/Facebook/etc) login with chrome extension manifest v3

Manifest version 3 for Chrome extensions have been killing me lately. Been able to navigate around it so far, but this one has really stumped me. I'm trying to use Firebase authentication for a Chrome extension, specifically with 3rd party auth providers such as Google and Facebook. I've setup the Firebase configuration for Login with Google and created a login section in the options page of the Chrome extension and setup the Firebase SDK.
Now, there are two login options when using an auth provider, signInWithRedirect and signInWithPopup. I've tried both of these and both have failed for different reasons. signInWithRedirect seems like a complete dead end as it redirects to the auth provider, and when it attempts to redirect back to the chrome-extension://.../options.html page, it just redirects to "about:blank#blocked" instead.
When attempting to use signInWithPopup, I instead get
Refused to load the script 'https://apis.google.com/js/api.js?onload=__iframefcb776751' because it violates the following Content Security Policy directive: "script-src 'self'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.
In v2, you could simply add https://apis.google.com to the content_security_policy in the manifest. But in v3, the docs say
"In addition, MV3 disallows certain CSP modifications for extension_pages that were permitted in MV2. The script-src, object-src, and worker-src directives may only have the following values:"
self
none
Any localhost source, (http://localhost, http://127.0.0.1, or any port on those domains)
So is there seriously no way for a Google Chrome extension to authenticate with a Google auth provider through Google's Firebase? The only workaround I can think of is to create some hosted site that does the authentication, have the Chrome extension inject a content script, and have the hosted site pass the auth details back to the Chrome extension through an event or something. Seems like a huge hack though and possibly subject to security flaws. Anyone else have ideas??
Although it was mentioned in the comments that this works with the Google auth provider using chrome.identity sadly there was no code example so I had to figure out myself how to do it.
Here is how I did it following this tutorial:
(It also mentions a solution for non-Google auth providers that I didn't try)
Identity Permission
First you need permission to use the chrome identity API. You get it by adding this to your manifest.json:
{
...
"permissions": [
"identity"
],
...
}
Consistent Application ID
You need your application ID consistent during development to use the OAuth process. To accomplish that, you need to copy the key in an installed version of your manifest.json.
To get a suitable key value, first install your extension from a .crx file (you may need to upload your extension or package it manually). Then, in your user data directory (on macOS it is ~/Library/Application\ Support/Google/Chrome), look in the file Default/Extensions/EXTENSION_ID/EXTENSION_VERSION/manifest.json. You will see the key value filled in there.
{
...
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgFbIrnF3oWbqomZh8CHzkTE9MxD/4tVmCTJ3JYSzYhtVnX7tVAbXZRRPuYLavIFaS15tojlRNRhfOdvyTXew+RaSJjOIzdo30byBU3C4mJAtRtSjb+U9fAsJxStVpXvdQrYNNFCCx/85T6oJX3qDsYexFCs/9doGqzhCc5RvN+W4jbQlfz7n+TiT8TtPBKrQWGLYjbEdNpPnvnorJBMys/yob82cglpqbWI36sTSGwQxjgQbp3b4mnQ2R0gzOcY41cMOw8JqSl6aXdYfHBTLxCy+gz9RCQYNUhDewxE1DeoEgAh21956oKJ8Sn7FacyMyNcnWvNhlMzPtr/0RUK7nQIDAQAB",
...
}
Copy this line to your source manifest.json.
Register your Extension with Google Cloud APIs
You need to register your app in the Google APIs Console to get the client ID:
Search for the API you what to use and make sure it is activated in your project. In my case Cloud Firestore API.
Go to the API Access navigation menu item and click on the Create an OAuth 2.0 client ID... blue button.
Select Chrome Application and enter your application ID (same ID displayed in the extensions management page).
Put this client ID in your manifest.json. You only need the userinfo.email scope.
{
...
"oauth2": {
"client_id": "171239695530-3mbapmkhai2m0qjb2jgjp097c7jmmhc3.apps.googleusercontent.com",
"scopes": [
"https://www.googleapis.com/auth/userinfo.email"
]
}
...
}
Get and Use the Google Auth Token
chrome.identity.getAuthToken({ 'interactive': true }, function(token) {
// console.log("token: " + token);
let credential = firebase.auth.GoogleAuthProvider.credential(null, token);
firebase.auth().signInWithCredential(credential)
.then((result) => {
// console.log("Login successful!");
DoWhatYouWantWithTheUserObject(result.user);
})
.catch((error) => {
console.error(error);
});
});
Have fun with your Firebase Service...

How to fix "Callback URL mismatch" NextJs Auth0 App

I am using Auth0 NextJs SDK for authentication in my NextJS App. I am following this tutorial https://auth0.com/blog/introducing-the-auth0-next-js-sdk/. In my local machine, everything works fine.
The configuration for Auth0 in my local server:
AUTH0_SECRET=XXXXX
AUTH0_BASE_URL=http://localhost:3000
AUTH0_ISSUER_BASE_URL=https://myappfakename.us.auth0.com
AUTH0_CLIENT_ID=XXXX
AUTH0_CLIENT_SECRET=XXXX
In the Auth0 Dashboard, I added the following URLs :
Allowed Callback URLs: http://localhost:3000/api/auth/callback
Allowed Logout URLs: http://localhost:3000/
My local app works locally fine.
I uploaded the app on Vercel. And changed the
AUTH0_BASE_URL=https://mysitefakename.vercel.app/
In Auth0 Dashboard, updated the following information:
Allowed Callback URLs: https://mysitefakename.vercel.app/api/auth/callback
Allowed Logout URLs: https://mysitefakename.vercel.app
I am getting the following error:
Oops!, something went wrong
Callback URL mismatch.
The provided redirect_uri is not in the list of allowed callback URLs.
Please go to the Application Settings page and make sure you are sending a valid callback url from your application
What changes I should make it works from Vercel as well?
You can try to check if vercel isn't changing the url when redirecting to auth0. Your configurations seems good to me. The error is very explicit though. I think a good option should be to verify that the redirect (if handled by vercel) is doing with the same url as auth0 expects.
And don't forget to add the url you're currently on when performing the callback. Are you in https://mysitefakename.vercel.app/api/auth/callback when the callback is executed? (call auth0).
you have to change your base url in the env.local file
AUTH0_BASE_URL=https://mysitefakename.vercel.app/
you can also make two more env files namely env.development and env.production and set different base urls for different cases so that the correct base url is automatically loaded depending on how ur web app is running.
You need to add handleLogin under api/auth/[...auth0].js and that will solve it:
import { handleAuth, handleLogin } from '#auth0/nextjs-auth0';
export default handleAuth({
async login(request, response) {
await handleLogin(request, response, {
returnTo: '/profile',
});
},
});
Don't forget to also add allowed callback url in [Auth0 Dashboard]: https://manage.auth0.com/dashboard for your hosted app for both local and hosted instance:
http://localhost:3000/api/auth/callback, https://*.vercel.app/api/auth/callback

Specify custom redirect_uri in a web app that uses Azure AD authentication with oidc and a middleware

I am trying to authenticate an app with Azure AD. It's all good in localhost, it redirects to Azure AD where I enter details to authenticate, and it sends back the token that allows to view the resource.
Everything managed behind the scenes with the Microsoft.AspNetCore.Authentication.AzureAD.UI 3.1.10 in an aspnetcore 3.1 application.
My app runs on http://localhost:5000 and I can configure the redirectUri/replyUri at Azure AD for that application to support this url. All good.
The problem is in a different environment when my app runs in a service fabric cluster.
I can see the problem
AADSTS50011: The reply URL specified in the request does not match the reply URLs configured for the application
When I inspect the url I can see that the redirect_uri has some url like this http://12.12.12.12/signin-oidc
The problem is double here. First of all I don't know which IP the cluster is gonna assign. Second, it is http, not https, and that's not supported by Azure AD.
Luckily my app has an external Url with a reverse proxy I can use to access. Something like https://myservicefabriccluster.com/MyApp
That Url I could configure as my redirect_uri in both my application and Azure AD, but I don't know how to do so.
My code has something like this:
services
.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => Configuration.Bind("AzureAd", options));
where I bind my settings.
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"ClientId": "76245c66-354e-4a94-b34d-...",
"TenantId": "59c56bd4-ce18-466a-b515-..."
},
I can see the AzureADOptions supports some other parameters such as Domain (not needed) or CallbackPath (which by default is ok being /signin-oidc) but there is nothing similar to ReplyUrl or RedirectUri where I can specify an absolute URL as the callback.
I have found a few similar issues without an answer. Others suggest some kind of tricks like a middleware that rewrites that parameter just before redirecting to Azure AD.
Certainly there must be an easier way to deal with this problem that I expect is not so strange. Any help please?
The solution to overwrite redirect_uri parameter with a custom value is to use the Events available in OpenIdConnect library. This library should be available as it's a dependency for Microsoft.AspNetCore.Authentication.AzureAD.UI, so this is my solution that, in addition to the standard properties for AzureADOptions it adds a flag to determine whether the redirect uri must be overwritten and a value to do so. I hope it's self explanatory
services
.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => configuration.Bind("AzureAd", options));
var isCustomRedirectUriRequired = configuration.GetValue<bool>("AzureAd:IsCustomRedirectUriRequired");
if (isCustomRedirectUriRequired)
{
services
.Configure<OpenIdConnectOptions>(
AzureADDefaults.OpenIdScheme,
options =>
{
options.Events =
new OpenIdConnectEvents
{
OnRedirectToIdentityProvider = async ctx =>
{
ctx.ProtocolMessage.RedirectUri =
configuration.GetValue<string>("AzureAd:CustomRedirectUri");
await Task.Yield();
}
};
});
}
services
.AddAuthorization(
options =>
{
options.AddPolicy(
PolicyConstants.DashboardPolicy,
builder =>
{
builder
.AddAuthenticationSchemes(AzureADDefaults.AuthenticationScheme)
.RequireAuthenticatedUser();
});
});
And the appsettings.json would have something like this:
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"ClientId": "76245c66-354e-4a94-b34d-...",
"TenantId": "59c56bd4-ce18-466a-b515-..."
"IsCustomRedirectUriRequired": true,
"CustomRedirectUri": "https://platform-cluster-development01.cubictelecom.com:19008/Scheduler/WebApi/signin-oidc"
},
Notice the IsCustomRedirectUriRequired and CustomRedirectUri are my custom properties that I read explicitly in order to overwrite (or not) the redirect uri query parameter when being redirected to the identity provider (i.e: Azure AD)
Looking at this, you should be configuring the public URL as the redirect URI, which is a value such as this:
https://myservicefabriccluster.com/MyApp
It looks like that the above library does not easily support this, and forces the redirect URI to be based on the HTTP listening URL of the code. As part of resolving this it is worth considering how you are writing your code:
This line of code indicates that your app is limited to only ever working with Azure AD:
- services.AddAzureAD
This line of code would ensure that your code works with both AzureAD and any other Authorization Server that meets the Open Id Connect standard:
- services.AddOpenIdConnect
The latter option also has an Events class with a commonly used OnRedirectToIdentityProvider operation that you can use to override the CallbackPath and provide a full RedirectUri.
Azure AD endpoints are standards based so you do not strictly have to use AzureAD specific libraries. Out of interest, I have a Single Page App Azure code sample that uses a neutral library like this, so I know this technique works.

Oauth2 Authorization in NelmioApiDocBundle

I am trying to use the NelmioApiDocBundle for a Symfony 3.4 projects API documentation, while also trying to wrap my head around OAuth 2 authorization for the project API access to begin with.
So far I've followed this tutorial on how to get FOSOAuthServerBundle working. So far I can
1.) create a client using the command line command:
php bin/console fos:oauth-server:create-client --redirect-uri="___" --grant-type="authorization_code" --grant-type="password" --grant-type="refresh_token" --grant-type="token" --grant-type="client_credentials"
2.) I can also get an access token manually by visiting this url on my server
http://127.0.0.1:8000/oauth/v2/token?client_id=______&client_secret=________&grant_type=client_credentials
3.) I can use the token to access areas of my Symfony project requiring OAuth Access by including the token in a GET parameter
However, in the NelmioApiDocBundle Authorizations I cannot get this to work to completion. Here is a screenshot:
If enter my client_id and secret key it takes me to the Login Page, as expected. I can enter my login information and in takes me to the Approve or Deny Page, as expected. At this point if I click either Approve or Deny it tries to use a "redirect_uri" of http://localhost:3200/oauth2-redirect.html. No matter what I do I cannot change the redirect URI.
How to I get the a proper redirect URI?
Ok, this was actually easily fixed. You need to add a single line:
oauth2RedirectUrl: 'URLhere',
to the file init-swagger-ui.js which is located (Symfony 3.4) in web/bundles/nelmioapidoc/
The final file ended up looking like this:
window.onload = () => {
const data = JSON.parse(document.getElementById('swagger-data').innerText);
const ui = SwaggerUIBundle({
oauth2RedirectUrl: 'URLhere',
spec: data.spec,
dom_id: '#swagger-ui',
validatorUrl: null,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: 'StandaloneLayout'
});
window.ui = ui;
};
Also you likely are going to want to download the file oauth2-redirect.html from the Swagger project to include for the actual redirect.

Resources