I'm trying to provide SSO to a next.js app with Okta but it's not working and I don't know why. Worked perfect;y with Google.
I get the error: [next-auth][error][GET_AUTHORIZATION_URL_ERROR] https://next-auth.js.org/errors#get_authorization_url_error only valid absolute URLs can be requested
and stack output:
provider: {
id: 'okta',
name: 'Okta',
type: 'oauth',
wellKnown: 'xxxxxxx.okta.com/.well-known/openid-configuration',
authorization: { params: [Object] },
idToken: true,
profile: [Function: profile],
checks: [ 'state' ],
clientId: 'xxxxxxxxxx',
clientSecret: 'xxxxxxxxx',
issuer: 'xxxxx.okta.com',
signinUrl: 'http://localhost:3000/api/auth/signin/okta',
callbackUrl: 'http://localhost:3000/api/auth/callback/okta'
},
message: 'only valid absolute URLs can be requested'
It's frustrating because I have no idea what the issue is. The callback and signinURI look fine and match what I entereed in Okta web app setup.
In [...nextauth].js I have tried to enable debugging but that gave me zero extra output:
export default NextAuth({
providers: [
OktaProvider({
clientId: process.env.OKTA_CLIENT_ID,
clientSecret: process.env.OKTA_CLIENT_SECRET,
issuer: process.env.OKTA_DOMAIN,
}),
GoogleProvider({
clientId: process.env.GOOGLE_ID,
clientSecret: process.env.GOOGLE_SECRET,
}),
],
debug: true,
});
If anyone has any ideas I would be super grateful. It would be nice to at least know what next-auth is doing under the hood - like checking which url it is trying to reach etc.
Many thanks!
Tony
I just tried this today and indeed I got the same error -- my fix was to add https:// to the front of the issuer value and that seemed to make it work (which was interesting because the tutorial I was following specifically said to omit it).
eg instead of:
issuer: 'xxxxx.okta.com',
I used:
issuer: 'https://xxxxx.okta.com',
and that seemed to resolve my issue.
Hope this helps!
I put together a blog post for setting up Next.js, NextAuth.js, and Okta. It gives examples of your //pages/api/[...nextauth].ts file and .env.local as well. It shows using https for issuer variable as well.
https://thetombomb.com/posts/nextjs-nextauth-okta
Related
NextAuth v4 implemented the possibility of configuring providers using the OIDC Discovery feature, that is, by defining just a wellKnown option (here) pointing to this discovery endpoint provided by the Authorization Service, e.g.:
export const oauthCustomProviderConfig = {
id: 'myprovider',
name: 'MyProvider',
type: 'oauth',
version: '2.0',
wellKnown:
process.env.A6_APP_OAUTH_PROVIDER_DISCOVERY_ENDPOINT ||
'http://localhost:9081/auth/realms/myrealm/.well-known/openid-configuration',
idToken: true,
issuer: process.env.A6_APP_OAUTH_PROVIDER_ISSUER || 'realms/myrealm/',
checks: ['pkce', 'state'],
async profile(profile, tokens) {
return {
id: profile.sub,
name: profile.name,
email: profile.email,
image: profile.picture,
};
},
clientId: process.env.A6_APP_OAUTH_CLIENT_ID || 'clientId',
clientSecret: process.env.A6_APP_OAUTH_CLIENT_SECRET || 'clientSecret',
};
This works fine, but then in order to develop a "Refresh Token Rotation" solution, we have to manually call the Token endpoint of our provider. As per the linked documentation:
async function refreshAccessToken(token) {
try {
const url =
"https://oauth2.googleapis.com/token?" +
new URLSearchParams({
client_id: process.env.GOOGLE_CLIENT_ID,
client_secret: process.env.GOOGLE_CLIENT_SECRET,
grant_type: "refresh_token",
refresh_token: token.refreshToken,
})
...
I would expect to be able to access the configured Token endpoint using the getProviders() feature (here), however, this doesn't provide the configured endpoints:
{
myprovider: {
id: 'myprovider',
name: 'MyProvider',
type: 'oauth',
signinUrl: 'http://localhost:90/api/auth/signin/myprovider',
callbackUrl: 'http://localhost:90/api/auth/callback/myprovider'
}
}
I think the only solution at this point would be to manually provide the Token endpoint as a configuration in my application, or to explore the discovery endpoint manually (adding a request each time we refresh the token), which makes the use of the wellKnown feature not optimal.
Is there a way to obtain the configured Token endpoint from the configured provider?
I have configured the OAuth client on RedHat OpenShift so that I can do SSO for my application using the inbuilt OAuth server of the RedHat OpenShift cluster. I got redirected to OCP login page, authenticated via OCP, and got the access_token as well. But now I want to get userinfo from the token I got. But it seems API /oauth/userinfo is not returning the user information.
Getting this error when I try GET /oauth/userinfo
REST API /oauth/userinfo
Am I missing something?
The /oauth/userinfo is apparently not there. You can get the user information using OpenShift API itself /apis/user.openshift.io/v1/users/{name}
The thing that I was missing is that a current logged in user is returned when you put ~ (tilde) to the path, so GET /apis/user.openshift.io/v1/users/~
{
kind: "User",
apiVersion: "user.openshift.io/v1",
metadata: {
name: "kube:admin",
selfLink: "/apis/user.openshift.io/v1/users/kube%3Aadmin",
creationTimestamp: null,
},
identities: null,
groups: [
"system:authenticated",
"system:cluster-admins",
],
}
As I'm using CodeReady containers for the development, I have URLs set up like this (Node.js/Next.js/next-auth):
export const OpenShiftOAuthProvider = {
id: "openshift",
name: "OpenShift",
type: "oauth",
version: "2.0",
params: { grant_type: "authorization_code" },
scope: "user:full",
idToken: false,
accessTokenUrl: "https://oauth-openshift.apps-crc.testing/oauth/token",
profileUrl: "https://api.crc.testing:6443/apis/user.openshift.io/v1/users/~",
authorizationUrl:
"https://oauth-openshift.apps-crc.testing/oauth/authorize?response_type=code",
clientId: "<yourclientid>",
clientSecret: "<yourclientsecret>"
async profile(profile) {
return {
id: profile.metadata.name,
name: profile.metadata.name
};
},
};
I use Passport.js to authenticate with Google. I define the following scope:
passport.authenticate('google', {
scope: [
'https://www.googleapis.com/auth/gmail.modify',
],
})
So, I just would like to access the Gmail API.
Now, Google responds with:
GooglePlusAPIError: Insufficient Permission
I get it working when I add the Google+ API to my projekt via the Google API dashboard and by adding the following scope to my passport.authenticate call:
'https://www.googleapis.com/auth/userinfo.email'
But why do I need the Google+ API when the only thing I would like to do is access Gmail?
I also found this website: https://developers.google.com/gmail/api/auth/web-server where they set these scopes:
SCOPES = [
'https://www.googleapis.com/auth/gmail.readonly',
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile',
# Add other requested scopes.
]
What am I missing?
Thanks in advance!
Cheers,
Niels
Edit:
I just researched on my Google API dashboard and found the screen below. So, are these scopes mandatory?
Edit 2
The context is an Express.js app. The whole call looks like:
router.get('/google', passport.authenticate('google', {
scope: [
'https://www.googleapis.com/auth/gmail.modify',
],
}));
router.get('/google/callback', passport.authenticate('google', {
failureRedirect: '/',
}), (req, res) => {
req.session.token = req.user.token;
res.redirect('/');
});
I want to use coturn with oAuth. If I understood it correctly I need to do two things:
Storing the oAuth tokens in the database coturn is using
Sending the ACCESS-TOKEN and USERNAME STUN attributes
First point is clear but how do I need to change my WebRTC client to achieve the second point?
Without oAuth I would initialize my RTCPeerConnection like this:
var configuration = {
'iceServers': [{
'url': 'turn:turn.example.org',
'username': 'user',
'credential': 'password'
}]
};
var pc = new RTCPeerConnection(configuration)
The WebRTC 1.0 draft defines a RTCIceCredentialType enum so i would think I need to change my configuration like this:
var configuration = {
'iceServers': [{
'url': 'turn:turn.example.org',
'username': 'kid',
'credential': 'oAuthToken',
'credentialType': 'token'
}]
};
Using Wireshark I can't see the ACESS-TOKEN attribute. Any ideas or does anyone know a working example?
It seems like things changed a bit since original question was asked. The webrtc-pc#1033 pull-request alters the spec and introduces the following iceServers configuration syntax:
var configuration = {
'iceServers': [{
"urls": "turns:turn.example.net",
"username": "username",
"credential": {
"macKey": "...",
"accessToken": "..."
},
"credentialType": "oauth"
}],
...
}
See RTCIceServer documentation page for more configuration examples.
I've downloaded the oauth2orize provider code example and the sample oauth client suggested in the docs and I'm getting the following error:
500 AuthorizationError: not authorized at validated
(/Users/trevorallred/projects/pics/node-soa/oauth2orize/examples/all-grants/node_modules/oauth2orize/lib/middleware/authorization.js:131:36)
at
/Users/trevorallred/projects/pics/node-soa/oauth2orize/examples/all-grants/oauth2.js:180:14
at Object.exports.findByClientId
(/Users/trevorallred/projects/pics/node-soa/oauth2orize/examples/all-grants/db/clients.js:24:10)
at exports.authorization.res.render.transactionID
(/Users/trevorallred/projects/pics/node-soa/oauth2orize/examples/all-grants/oauth2.js:174:16)
at
/Users/trevorallred/projects/pics/node-soa/oauth2orize/examples/all-grants/node_modules/oauth2orize/lib/middleware/authorization.js:167:9 at pass
(/Users/trevorallred/projects/pics/node-soa/oauth2orize/examples/all-grants/node_modules/oauth2orize/lib/server.js:262:26)
at pass
(/Users/trevorallred/projects/pics/node-soa/oauth2orize/examples/all-grants/node_modules/oauth2orize/lib/server.js:280:9)
at pass
(/Users/trevorallred/projects/pics/node-soa/oauth2orize/examples/all-grants/node_modules/oauth2orize/lib/server.js:271:11)
at Server._parse
(/Users/trevorallred/projects/pics/node-soa/oauth2orize/examples/all-grants/node_modules/oauth2orize/lib/server.js:285:5)
at authorization
(/Users/trevorallred/projects/pics/node-soa/oauth2orize/examples/all-grants/node_modules/oauth2orize/lib/middleware/authorization.js:118:12)
I'm running the client here: http://localhost:3002/
I click the link to "Connect with example-oauth2orize"
It redirects me to the provider: http://localhost:3000/login
After logging in with "bob" I'm sent to this error page.
The only modifications I've made are to oauth-config.js in the example client.
'use strict';
module.exports = {
provider: {
protocol: "http",
host: "localhost:3000",
profileUrl: "/api/userinfo"
},
consumer: {
protocol: "http",
host: "localhost:3002"
}
};
I tried modifying oauth-consumer-config.js after I saw this bug report but it didn't seem to change any behavior.
module.exports = {
name: 'Example Consumer App'
, icon: 'http://example.com/icon_64.png'
, clientId: 'trevorclient'
, clientSecret: 'kasdfasdfoq34t134tg109gqerg1gjc'
};
Try updating your oauth-consumer-config.js file to this:
module.exports = {
name: 'Example Consumer App'
, icon: 'http://localhost:3000/icon_64.png'
, clientId: 'abc123'
, clientSecret: 'ssh-secret'
};
The problem is that the all-grants example doesn't actually use a DB, but a flat file for illustration purposes. If you navigation to db/clients.js in the all-grants project, you'll see the clients listed there that are allowed to connect via OAuth.