auth0 / express-openid-connect Goto Github PK
View Code? Open in Web Editor NEWAn Express.js middleware to protect OpenID Connect web applications.
License: MIT License
An Express.js middleware to protect OpenID Connect web applications.
License: MIT License
The three routes that this middleware uses expect a relative path from the root but it does not validate that a leading /
is included:
https://github.com/auth0/express-openid-connect/blob/master/lib/config.js#L31
The docs suggest that you can use refresh tokens by requesting the offline_access scope, however this conflicts with the behavior in the source, which suggests that if the response_type
is code
that the refresh flow will use PKCE.
I don't view this as being as simple as removing the conflicting example from the docs, because the example treats with what I view as a core use-case of this library: providing a refresh token to use from the JS side of your application. There is no obvious way (nor am I confident that it is secure) to pass the PKCE challenge to a client and even if you get the PKCE challenge to the client, auth0 does not provide a clear path to inject the PKCE challenge into a browser client. I'm happy to open up a pull request removing the conflicting API example if it doesn't make sense to include a replacement for the old flow.
You can reproduce this issue by trying to read an accessToken off of the RequestContext when requesting Offline Access from your OIDC client.
Please provide the following:
I am migrating over to express-openid-connect from the auth0 passport flow and I seem to receive this error when trying to hit any of the endpoints (/login /logout etc): OPError: expected 200 OK with body but no body was returned.
Everything worked fine with the Passport flow. If I run my server (node index.js) in Windows, this error occurs when I try to hit any of the endpoints, however in the same environment using Ubuntu with WSL2, it works fine - Ubuntu itself also works fine.
The issue only seems to occur in my Windows environments. I tried this on 2 different computers.
The issue seems to be that nothing is returned when trying to get the .well-known config (error occurs at /openid-client/lib/helpers/process_response.js:48:11 so perhaps this is an openid issue?)
When hitting any of the provided endpoints like /login, I should be redirected to Universal Login, but instead I get this error.
I'm trying to understand whether it's possible to combine this library with a JWT projected API. Use case: I want to use Auth0 roles, and on my Express app provide /login and /login functionality with express-openid-connect, but also protect the page /createbook with the permission create:book of an Auth0 API (books).
Setup:
authorizationParams: {
response_type: "code",
audience: "books",
scope: "openid profile email access:gp create:book",
}
In the documentation, you mention we can use a server-side session storage to store the access_token. However, it should also be possible to store these client side right? I was thinking something like this:
handleCallback: async (req: any, res: any, next: any) => {
req.identity.claims.access_token = req.openidTokens.access_token;
next();
},
We could then use req.openid.user.access_token
combined with express-jwt-authz
to validate the permissions on the /createbook
route, correct?
Is this recommended / safe? And / or would it be enough to store req.openidTokens.scope
in the claims?
Would like the ability to specify my own callback url and not just have it default to "/callback"
In the example of using session handling I see that logout is redirecting to the identity server logout url.
But nowhere do I see where the cookies are cleared from the session.
The destroy function should be called: https://github.com/expressjs/session#sessiondestroycallback
Hello, I am currently in the process of testing the upgrade path to 2.0.0 of this library using Auth0 as my oauth provider. After logging in to Auth0, the callback endpoint fails with the following error: BadRequestError: connect ECONNREFUSED 127.0.0.1:443 at /Users/hsostock/code/connect-web/node_modules/express-openid-connect/middleware/auth.js:105:31 at processTicksAndRejections (internal/process/task_queues.js:97:5)
Note: After doing some debugging, it appears that this is the result of an internal call to https://{auth0-domain}/.well-known/oauth-authorization-server
returning a 404 Not Found
error (which, for some reason, is surfaced as the above connection refused error).
I am using the following configuration in my express app:
const app = express();
app.use(oidc.auth({
secret: "secret value",
routes: {
login: '/auth/login',
logout: '/auth/logout',
postLogoutRedirect: '/',
callback: '/auth/callback',
},
session: {
rolling: false,
absoluteDuration: 60, // 60 seconds
},
authRequired: true,
auth0Logout: true,
clientID: "secret value",
clientSecret: "secret value",
baseURL: config.webUrl,
issuerBaseURL: config.auth.issuerBaseURL,
authorizationParams: {
scope: 'openid profile email offline_access',
response_type: 'code',
},
}));
And occurs consistently (as mentioned) when validating the authorization code returned from Auth0.
After logging in I get no client authentication mechanism provided
. I use oidc-provider
with the following client:
{
client_id: "foo",
client_secret: "bar",
token_endpoint_auth_method: "client_secret_post",
redirect_uris: ["http://localhost:3000", "http://localhost:3000/callback"],
grant_types: ["authorization_code", "refresh_token"],
response_types: ["code"]
}
This is my auth config:
{
clientID: "foo",
clientSecret: "bar",
authorizationParams: {
response_type: 'code',
response_mode: 'form_post',
scope: 'openid email offline_access'
}
}
I can manually curl
to get the tokens like described here
I would appreciate any pointers.
I am receiving the following error when using this library in conjunction with the Auth0 guide:
TypeError: option sameSite is invalid
at Object.serialize (/home/bryce/wslcode/.../node_modules/cookie/index.js:174:15)
at ServerResponse.res.cookie (/home/bryce/wslcode/.../node_modules/express/lib/response.js:853:36)
at Object.store (/home/bryce/wslcode/.../node_modules/express-openid-connect/lib/transientHandler.js:32:7)
at ResponseContext.login (/home/bryce/wslcode/.../node_modules/express-openid-connect/lib/context.js:91:26)
at processTicksAndRejections (internal/process/task_queues.js:88:5)
I have tried to work out where the error is coming from but can't quite see how it's occurring.
My config:
const config = {
required: false,
auth0Logout: true,
appSession: {
secret: process.env.APP_SECRET,
},
baseURL: process.env.BASE_URL,
clientID: process.env.AUTH0_CLIENT_ID,
issuerBaseURL: process.env.AUTH0_HOST,
};
Please provide the following:
Hey guys !
I am using your lib on my backend app. Everything works fine !
But I wonder how I should implement on my frontend app.
Does the makeTokenSet function generate an access_token which I can use by simply putting it in the header (Authorization: Bearer <access_token>) of my API calls ?
Currently it seems to be directly redirected to openId provider.
openId.auth({
required: req => !(req.originalUrl.includes('/checkAuthentication') || req.originalUrl.includes('/login')),
issuerBaseURL: config.issuerBaseURL,
baseURL: config.baseURL,
clientID: config.clientID,
clientSecret: config.clientSecret,
appSessionSecret: config.appSessionSecret,
authorizationParams: {
response_type: 'code',
scope: 'openid profile email'
},
handleCallback: function (req, res, next) {
// This will store the user identity claims in the session
req.session.user = req.openidTokens.claims();
req.session.openidTokens = req.openidTokens;
console.log(req.session.openidTokens);
next();
},
})
I'm pretty clear on how to retrieve user profile info for display in my app, but how do I edit it?
Functionality within the library itself would be ideal, but is there a workaround where I can send users to an auth0 web page to edit their profiles?
Is this library recommended for the scenario where spa and backend are on different subdomains?
I am not able to find a way to do the final redirect to a different subdomain (i.e., redirect to subdomain belonging to app with cookie being set)
For now I am using another set of redirect, post the setting of cookies, just to redirect from backend subdomain to app subdomain.
Is this flow recommended?
I would like to default to a connection, e.g. google-oauth2
Pass in a configuration option to the middleware similar to auth0-spa-js's loginOptions, e.g. { connection: "google-oauth2" }
N/A
Standard setup, but using a single connection for an application. It would be nice to redirect to the Google account selection page without having to click "Continue with Google".
Hello,
The README states:
"This library is currently in Beta status and has not had a complete security review. We do not recommend using this library in production yet"
Do you have an ETA for when this will be ready for production use please?
Thanks,
Dan
Hi,
Thank you for your work on v2.
In my use case I need to call userinfo and the v2 api makes it really simple. In v1 I have to keep around users' tokenset with express-session for example.
The issue I have is the size of the appSession cookies (plural because they are chunked in several cookies).
A bit more than 4k in my case, is it due to my setup? (I guess a tokenset is stored in the cookies which explains the simplified userinfo api). V1 appSession cookies are ~500 bytes.
For each request+response from the browser to the api the cookies are sent as part of the request and updated cookies are sent from the api.
I think I wouldn't have noticed immediately but the default configuration of nginx (used as reverse proxy in front of the api) doesn't let these large headers go through: (due to the cookie size I think)
[error] 27#27: *897 upstream sent too big header while reading response header from upstream, client: 172.18.0.1, server: , request: "POST /api/auth/callback HTTP/1.1", upstream: "http://172.18.0.5:3001/api/auth/callback"
nginx can be configured to allow this using for example:
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
What do you think about it?
The tokenset has to be stored somewhere but it's not always needed for very simple usecases right?
installed package have different definition with github repository
should have same index.d.ts with github master branch
express-openid-connect: 2.0.0.
node: v12.19.0
npm: v6.14.8
Hey, I'm interested if there is a way for using this lib with the "Authorization Code Flow" ?
And if so, what configuration should I add?
According to the SessionConfigParams
you should be able to set the transient property like so:
app.use(
auth({
session: {
transient: true,
},
})
);
However this throws TypeError: "session.transient" is not allowed
.
The correct code is:
app.use(
auth({
session: {
cookie: {
transient: true,
},
},
})
);
But this is not how it is defined in the interface.
Using version 2.0.0.
getting race condition, after user is authenticated via auth() and not able to my corresponding landing page.
I am using sequelize store as store property in the expression- session.
This is how my express session looks like:-
const expressSession = session({
resave: false,
saveUninitialized: false,
store: SequelizeStore,
name: "bbb",
secret: "b3c1d6a7-06b2-4c04-99c9-a52994fpad9a",
proxy: true,
cookie: {
httpOnly: true,
sameSite: "lax",
secure: true,
maxAge
}
});
Able to fix the issue by adding below code
req.session.save(function () {
res.redirect(returnTo);
});
in requesthandler after config.handleCallback in middleware/auth js.
Not sure if this correct way. Kindly let me know if its a known bug or if there is any plan for the fix
I've been trying to configure Auth0 following the quickstart guide and setting up the configurations as per the documentation. But afterwards I can't seem to navigate to any route, even the /login auth0 route without getting the above mentioned error message.
This is my configuration code
export const config = { required: false, auth0Logout: true, appSession: { secret: process.env.AUTH0_CLIENT_SECRET }, baseURL: 'http://localhost:3001', clientID: process.env.AUTH0_CLIENT_ID, issuerBaseURL: process.env.AUTH0_DOMAIN };
The app using Auth0
`import express from 'express';
import { auth, requiresAuth } from 'express-openid-connect';
import { config } from './controllers/authController';
const app = express();
app.use(express.json());
app.use(auth(config));
// req.isAuthenticated is provided from the auth router
app.get('/', (req, res) => {
res.send(req.isAuthenticated() ? 'Logged in' : 'Logged out');
});
app.get('/profile', requiresAuth(), (req, res) => {
res.send(JSON.stringify(req.openid.user));
});`
the error message i keep getting
AggregateError: TypeError: only valid absolute URLs can be requested at module.exports (C:/Users/Paul Nisiro/Documents/Projects/Node/farmrail/src/services/user_api/node_modules/openid-client/lib/helpers/is_absolute_url.js:10:11)
Unable to use the property in typescript project because of the missing property
I have this module installed in my Express app, and while it seems to work perfectly fine when attempting to make a GET request to a protected endpoint in the browser, making the same request in postman results in this response being returned regardless of what protected endpoint I try to hit:
<html>
<head>
<title>Submit This Form</title>
</head>
<body onload="javascript:document.forms[0].submit()">
<form method="post" action="http://localhost:3000/callback">
<input type="hidden" name="id_token" value="eyJhbGciOiJSUzI1NiIsInR5cCI6Ikp..."/><input type="hidden" name="state" value="eyJyZXR1cm5..."/></form>
</body>
</html>
(Tokens redacted of course).
I have set up Postman according to this guide and I am able to successfully log in and get a bearer token using it
https://auth0.com/blog/manage-a-collection-of-secure-api-endpoints-with-postman/
I then make a request to a protected endpoint that ought to return a simple JSON object, but instead get the above HTML with a status code of 200
Node 10.22.0
Express 4.17.1
express-openid-connect 2.0.0
Windows 10
Postman 7.34.0
Any thoughts on adding capability to query the user info endpoint?
I am using appSession. After successful login, if the server's APP_SESSION_SECRET is changed, library throws a 500 error with JWEDecryptionFailed.
JWEDecryptionFailed: decryption operation failed
at decrypt (/opt/app/node_modules/jose/lib/jwa/aes_gcm.js:42:11)
at decrypt (/opt/app/node_modules/jose/lib/jwa/index.js:86:32)
at jweDecrypt (/opt/app/node_modules/jose/lib/jwe/decrypt.js:165:21)
at decrypt (/opt/app/node_modules/express-openid-connect/lib/appSession.js:41:16)
at /opt/app/node_modules/express-openid-connect/lib/appSession.js:81:50
at Layer.handle [as handle_request] (/opt/app/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/opt/app/node_modules/express/lib/router/index.js:317:13)
at /opt/app/node_modules/express/lib/router/index.js:284:7
at Function.process_params (/opt/app/node_modules/express/lib/router/index.js:335:12)
at next (/opt/app/node_modules/express/lib/router/index.js:275:10)
This is a recoverable error. The library should behave as if the cookie was not in request and prompt the user to login. This should not be fatal.
Login and then manually modify the appSession cookie to break the AES-GCM decryption.
Please provide the following:
I'm having this error on my second attempt of login. After my token expired (24h), the APP redirects my user to the login screen (another service) and when it makes a successful login, it redirect my user to my APP giving this kind of errors:
Sometimes is error 1 or 2.
But despite this error, if the user goes to the home page he sees that he is logged in and he can starts use the APP.
This error gives a bad user experience.
Avoid the error page on callback page.
We are using Node JS with ** Express 4.17.1 **, everything works well except for the lines discussed above.
It seems that the issue is reproduced by transientHandler.js, exactly on the next lines:
getOnce(key, req, res) {
if (!req[COOKIES]) {
return undefined;
}
let value = getCookieValue(key, req[COOKIES][key], this.keyStore);
this.deleteCookie(key, res);
if (this.legacySameSiteCookie) {
const fallbackKey = `_${key}`;
if (!value) {
value = getCookieValue(
fallbackKey,
req[COOKIES][fallbackKey],
this.keyStore
);
}
this.deleteCookie(fallbackKey, res);
}
return value;
}
The value comes undefined and for that reason the APP makes an exception related to state mismatch.
Our OIDC configuration
module.exports = (app) => {
app.use(
auth({
issuerBaseURL: process.env.JZ_AUTH_AUTHORITY,
baseURL: process.env.JZ_BASE_URL,
clientID: process.env.JZ_AUTH_CLIENT_ID,
clientSecret: process.env.JZ_AUTH_CLIENT_SECRET,
// cookie
secret: "xxxxxxxxxxxxxxxxxxxxxxx",
session: {
name: "JZ_SC_SESSION",
rolling: false,
// 20 hours
absoluteDuration: 20 * 60 * 60,
cookie: {
// ignore https
secure: false
}
},
// authorization params given by identity server
authorizationParams: {
response_type: "code",
response_mode: "form_post",
scope: "openid email phone profile juntoz jz-public jz-core",
audience: process.env.JZ_AUTH_AUTHORITY,
state: "sitecentral"
},
// logout the user from identity server
idpLogout: true
})
);
}
Two browser tabs going through a login process at the same time can result in a state mismatch error.
Actual result: A state mismatch error
Expected result: A successful login
It appears that this middleware stores the nonce and state in a cookie, which when shared across tabs (or even across requests), invalidates previous login attempts because the previous values are overwritten. We also saw a similar issue where asset requests to our app were triggering the auth flow (this was due to a misconfiguration on our part) and invalidating the current login flow since new nonces/state were issued.
Potentially related issues:
aspnet/Security#179
I have the following Express setup:
//...
express()
.use(auth({
baseURL: '...',
required: false,
idpLogout: true,
issuerBaseURL: '...',
clientID: 'orderpages-client',
authorizationParams: {
response_type: 'id_token token',
response_mode: 'form_post',
scope: [
'openid',
'profile',
'email',
'address',
'phone',
'company_roles',
'company_profile',
'company_extended_profile',
// APIs
'customer-manager-api',
'referral-manager-api',
'order-pages-api',
].join(' ')
}
}))
.get('/user', requiresAuth(), (req, res) => res.json(req.openid.user))
//...
The last three of the scope are referring to API endpoints, which are called from the front-end application.
The idea is the following:
A React app served from the Express server, using express-openid-connect
and a custom IdP for auth.
The user logs in, and after that they can fetch their info through a /user
endpoint.
This should ideally contain all the information like openid, profile, email, address, etc. as given in scope, as well as an access_token, that can be later used to make authenticated requests to the APIs also defined in scope.
The user object though does not contain the required fields, if token is present in response_type
, which also breaks if scope contains any of the APIs.
When removing token, and the APIs from scope, the user object looks fine, containing all the required fields
I'm using
authorizationParams: {
response_type: 'code',
response_mode: 'query',
scope: 'openid email'
}
But when returned to the /callback
endpoint, the user receives BadRequestError: no valid key found
.
Turning on debugging doesn't reveal anything useful. Site output shows:
BadRequestError: no valid key found
at router.(anonymous function) (/Users/jt/Projects/oidc-test-client/node_modules/express-openid-connect/middleware/auth.js:123:27)
at process._tickCallback (internal/process/next_tick.js:68:7)
I expect this is to do with token verification and the keystore required by openid-client. How is this configured?
We could use form_post
instead of fragment
for fragment
response types IF the provider lists form_post as supported.
Typescript Definition for SessionConfigParams is outdated.
I've tried to set following:
session: {
secure: true,
},
Instead the following works:
session: {
cookie: {
secure: secureCookies,
},
},
Login callback returns Bad Request error after a successful login. Exception from server side:
BadRequestError: checks.state argument is missing
at callbackStack (/.../node_modules/express-openid-connect/middleware/auth.js:105:31)
Successful login callback and redirect to the set URL.
auth0Config:
"auth0Config": { "authRequired": false, "auth0Logout": true, "secret": "...", "baseURL": "https://www.joyridesclub.com", "routes": {"postLogoutRedirect": "https://www.joyridesclub.com/loggedout"}, "clientID": "...", "issuerBaseURL": "..." }
Node/Express web server
"express-openid-connect": "^2.1.0",
Hello,
we use the auth config which works with other library
app.use(
auth({
issuerBaseURL: `${URL}/.well-known/openid-configuration`,
authorizationParams: {
...
response_mode: 'form_post',
}
while running it we got an error, that the issuer supporting only query
of fragment
but not, we have old applications which works with the exact same issuer and we configure the issueBaseURL
exactly the same and the response_mode
is
form_post, why we are getting this error,is it known issue ? please explain how to proceed.
I propose a change to how tests are written after the discussion here: #40 (comment)
As mentioned, I would use the concept Avoid Nesting when you're Testing, in addition to avoid writing repetitive configs by gathering them on top of each file (or another centralized place like mockData.js
or something similar), and create a setup***()
function for tests in a single test suite (file).
Reducing the number of nested describe()
blocks would also improve readability, by flattening out the test suite. This would be much easier to achieve with the above mentioned setup***()
functions.
These are not BREAKING CHANGES ๐ฅ, as it only touches on the testing part. Though, it must be done carefully, so everything that is tested already is migrated first, and then maybe try to think about adding more tests.
I have mainly used Jest ๐ for testing, and after working on the logout.test.js
tests, I would much prefer to do that here as well. Mocha โ felt a bit cumbersome, and the outputs were not always easily readable IN MY OPINION.
I'm trying to develop against an OIDC provider where for a single issuer I may use several different sets of client authentication, even for a single client ID.
Currently, if I startup a single instance of express-openid-connect, I can only assign a single client secret. I would like to be able to dynamically "route" what client authentication I use based on the parameters of the "/login" request.
Expose client authentication as part of the LoginOptions interface, that way we can dynamically assign the client authentication credentials based on the request itself. Specifically, the /login request to my server will expect a query string param indicating what "instance" to route to and what client authentication to use at the token endpoint for that request.
For this use case, we know precisely what authentication to use by the time the "/login" request comes in.
I think it's a fair assumption that "Dynamic Client Credentials" will only depend on the "/login" request, and that we don't need to do anything fancy like a dynamic function at the "/callback" endpoint.
The challenging bit may be securing the authentication credentials used. For each login flow, we shouldn't be independently storing the client secret in the request's session, as this seems like a security risk. Maybe assigning a key or indicator to the request, and having a sort of key map built into the config would be best.
For instance, lets say that on my "/login" request I can receive a query string param called "issuer" that I will use to route my application. This parameter could have values of "issuer_1" or "issuer_2" which correspond to client secrets "secret_1" and "secret_2" respectively.
In my auth config, I could now include a "clientSecretMap" JSON object containing all of my client secrets keyed to the "issuer"
const config = {
// Other config...
clientSecretMap: {
"issuer_1": "secret_1",
"issuer_2": "secret_2"
}
};
Then, within a new parameter on the login request, we could dynamically "route" to any of these pre-configured keys based on the login request itself, rather than re-caching a dynamically generated secret in the requests session.
router.get('/launch', function(req, res, next) {
res.oidc.login({
// Other config ...
clientSecretKeyMap: req.query.issuer
});
})
If an application tried to route to an issuer that wasn't in the key-map, the request should fail rather than sending a null client secret. This map should be just smart enough so that the developer doesn't need to "double-check" the issuer before attempting to pass the key in.
I don't think we should allow for both a static clientSecret and a key map in the same config. Developers should choose one or the other, and if needed include a default key in their map that they can route to as needed.
I could spin up several instances of the application with duplicate config (other than the client credentials).
The thing is, this significantly increases startup time, and all of the startup middlewares would be independently calling to the same OIDC metadata endpoint.
I'm also not 100% on how managing several sets of this middleware in one process would work.
Current dev environment is...
my-dev-domain.com -> (30x redirect) -> some-dynamic-tunnel.ngrok.io
Given this setup, auth will not work because the configured callback domain (my-dev-domain.com in this case) cookies will not be set because of the 30x redirect that is happening above. Changing the callback domain manually won't help because the tunnel is dynamic and that would break a smooth workflow. The whole point of the setup above is to have a static redirect and smooth out the workflow.
Ideal solution is to configure the redirect uri to match the referrer, thus the cookies will be set on the tunnel address and all is well in the world.
The following commit to my fork works nicely. Auth0 allows wildcard callbacks and it's working excellently.
june07@667b766
The referrerRedirect option by default would have zero effect.
The following example generates an error saying that id_token code
is not supported. Then, I found out that code id_token
is what the library (or something else?) is expecting. Is this by design? Or room for improvement?
app.use(eoc.routes({
issuer_base_url: process.env.AUTH0_DOMAIN,
client_id: process.env.AUTH0_CLIENT_ID,
client_secret: process.env.AUTH0_CLIENT_SECRET,
base_url: appUrl,
authorizationParams: {
response_type: 'id_token code',
},
}));
Thank you for the great package.
How to use the getuser in the auth and refresh token . Please guide on this.
We tried this, but not working
app.use(auth({ getUser: (tokenSet) => {
console.log(tokenSet);
},
authorizationParams: { scope: "openid profile full", response_type: "code" }
}));
I am trying to develop against on OIDC provider that only accepts private_key_jwt client authentication, and am unable to with this middleware.
Add support for private_key_jwt and client_secret_jwt client authentication methods. In the startup config, a field for a JWKs set would be best, where the specific KID to be used on a request could be routed on login (similar to solution in this issue). If the JWK only had one key, then that could be used as a default client authentication value.
None for this library. I'm currently trying to wrap express around openid-client myself, but that loses a lot of the awesome functionality in this lib :)
Assuming a user has already logged in via the usual means, it would be handy to be able to use the session cookie to authenticate users during the WebSocket upgrade request (assuming websocket server and http server running on the same domain).
I don't think it's currently easy/possible to use this library to implement an authenticate function suitable for the upgrade request as in this code sample.
I'm relatively new to how openid connect works so I guess there could be some technical reason as to why this isn't possible.
An authenticate function with a matching signature or something you could just import or have optionally returned from calling auth
(or a similar function) would be ideal. Failing that, the ability to call a function to validate the session cookie and get the oidc
/oidc.user
objects/profile would probably do.
I browsed through the code and started hacking something together which returned the appSession
instance created here in an object along with the router.
I also added an if here to cope with a null
response object.
My plan was then to call it like this
import { get as getConfig } from 'express-openid-connect/lib/config';
import { RequestContext } from 'express-openid-connect/lib/context';
import { auth, requiresAuth } from 'express-openid-connect';
const authConfig = getConfig(authParams);
const { router, appSessionMiddleware } = (auth(authParams) as any);
// ...
server.on('upgrade', async (req, socket, head) => {
appSessionMiddleware(req, null, async req => {
try {
const oidc = new RequestContext(authConfig, req, null, () => console.log("next was called"))
const userInfo = await oidc.fetchUserInfo();
console.log("Got user info %s", userInfo);
} catch(e) {
console.log("Got err %s", e);
}
}
}
I then hit a problem with this line and remembered that the req object express gives you is different to the req/socket object you get from http, however it's still possible to get the cookie values from signedCookies
, I think it just has a slightly different interface.
I originally had a setup with passportjs and cookie-parser but that involved storing the sessions in a database and I was having trouble with data races which is what prompted me to switch to express-openid-connect.
I guess it would also be possible to have an ordinary authenticated api route to request a 'ticket' and implement a ticket based authentication system as described here. However I'm not sure quite what should go into a ticket and how large it would need to be to be reasonably secure.
With a bit more hacking on the code and some guidance I'm fairly confident I could put together a PR for this feature.
However it would be nice to be sure that I haven't missed something fundamental and this idea isn't totally flawed.
One of my applications that depends on express-openid-connect needs access to JWT in the routes. Prior to v.0.6.0, JWT was available in req.openid.tokens.id_token
.
After upgrading to v.0.6.0 I have attempted to follow the instructions (in point numbers 4 and 5) at https://github.com/auth0/express-openid-connect/blob/master/EXAMPLES.md. But what I am seeing is when I add a auth.handleCallback()
property, my RP becomes stuck in an infinite loop of requests between it and its OP.
In the RP log I see:
.. this pattern repeats over and over until I close the client web browser. If I remove the auth.handleCallback()
property, then authentication completes normally. But then I don't have access to the JWT.
Simplified Express (app.js) code, which still produces the issue:
const sessionOpts = {
secret: env.getSessionSecret(),
};
const authOpts = {
issuerBaseURL: env.getOidcOpUri(),
baseURL: env.getOidcRpUri(),
clientID: env.getOidcClientId(),
redirectUriPath: env.getOidcRedirectPath(),
required: true,
authorizationParams: {
response_type: 'id_token',
response_mode: 'form_post',
scope: 'openid profile email',
},
appSessionSecret: false,
handleCallback: async function(req, res, next) {
req.session.oidcTokens = req.openidTokens;
console.log('In the callback-handler');
console.dir(req.openidTokens);
next();
},
};
// Set up session, body parser, authn
app.use(session(sessionOpts));
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json({strict: false}));
app.use(auth(authOpts));
Allowing access to API (cross-domain) and treating the API request as authenticated and avoid redirecting to authorize/ end point
Hit localhost/app/app1 where internally front end of app1 is sending a request to localhost:8022/app/app1/fetch . Below is the code
Gateway App which is front facing app for all of the sub apps ( app0,app1,app2) - http://localhost/app/
App1 URL - http://localhost/app/app1/
API URL - http://localhost:8022/app/app1/fetch
Gateway App Code
`
const express = require('express');
const app = express();
//per application entry
const app0 = require("./app_folder1");
const app1 = require("./app_folder2");
const app2 = require("./app_folder3");
const app3 = require("./app_folder4");
require('dotenv').config();
const {
auth , requiresAuth
} = require('express-openid-connect');
app.use(auth({
required:function (req) {
console.log(req.isAuthenticated());
if (req.headers['x-requested-with'] === 'XMLHttpRequest')
return true;
else
return false;
},
issuerBaseURL: process.env.ISSUER_BASE_URL,
baseURL: process.env.BASE_URL,
clientID: process.env.CLIENT_ID,
clientSecret: process.env.APP_SESSION_SECRET,
redirectUriPath:'/app/callback',
authorizationParams: {
response_type: 'code',
scope: 'openid profile email',
custom_param: "custom-value",
response_mode: 'form_post',
},
idTokenAlg: 'RS256',
appSession: {
secret: process.env.APP_SESSION_SECRET,
duration: 3600
},
handleCallback: async function (req, res, next) {
req.appSession = req.appSession || {};
try {
next();
} catch (e) {
next(e);
}
}
}));
// Add headers
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*'); // for reverse proxy
next();
});
//per application path mapping
app.use('/app/app0/', app0);
app.use('/app/app1/', app1);
app.use('/app/app2/', app2);
app.use('/app/app3/', app3);
app.listen(8022);
`
Libraries and Dependencies
NodeJS - 11
express-openid-connect - 1.0.2
express - 4.16.3
Browser - Google Chrome
Identity provider - Okta
In the logout function, req.openid.tokens is used but this variable does not exist:
https://github.com/auth0/express-openid-connect/blob/master/lib/context.js#L137
It would be nice to have a function that returns the tokens (similar to the getUser function). And by default, save these tokens in cookies (http-only), but by having the function, the user will be able to use another method to save tokens (such as express-sessions).
At the same time the function would be very useful for the user to have the tokens, and use for example in calls to the api.
I want to call the login endpoint via AJAX request and simply get the redirect URL in the response.
I've not found a way to change this behavior without modifying the library source code.
So the possible solution is to have two methods: login, loginWithRedirect in the RequestContext class.
Hey, I wonder how to use this lib with a microservices architecture.
In my previous issue you added the link below(by the way thank you for the answer there and sorry for my inactivity)
So about the link I saw that the node server renders the html pages but what should I do if I just use the node server for RESP api?
(I would like to use the Authentication Code flow so the 'login' part would be from the frontend and the 'code to token' exchange would be from the backend)
https://github.com/auth0-samples/auth0-express-webapp-sample/tree/master/01-Login
Thank you
I have the following express implementation:
// ...
express()
.use(auth({
required: false,
idpLogout: true,
}))
//...
I use the default /login
, /logout
, /callback
routes.
idpLogout
is set to true
, because I want the user to be logged out from the Identity Provider as well. My problem is, that after logging out, they stay on the Identity Provider.
How can I pass a returnUrl
, so the user comes back to the site?
I tried putting this at the frontend <a href="/logout?returnUrl=http://example.com">Log out</a>
, but it did not help.
I'm trying to figure out how to create a route that will take people straight to Sign up (example: /register)
I tried this:
app.get('/register', (req, res) => {
res.openid.login({returnTo: '/', initialScreen: 'signUp'});
})
But that just took them straight to login like usual.
How can I send them to login page with Sign-Up Pre-selected?
When running tests, a particular test fails randomly.
npm test
Please provide the following:
Multiple places in the documentation refer to an audience
param (examples here and here). However, it's not clear to me what the value should be for audience
.
Add audience
to the API documentation and provide more specific examples than "https://your-api-identifier"
.
None identified. I'm still Googling trying to figure out the correct value for audience
.
I used the beta experimental Quickstart for Node to set up Auth0 in my app.
Sometimes while testing this I get:
BadRequestError: checks.state argument is missing
at <folder>/node_modules/express-openid-connect/middleware/auth.js:105:31
at processTicksAndRejections (internal/process/task_queues.js:97:5)
This happens randomly after logging in.
It happens especially often at the first login, but sometimes just randomly after logging in. My code:
require('dotenv').config()
const express = require('express')
const app = express()
const { auth } = require('express-openid-connect')
const config = {
authRequired: false,
auth0Logout: true,
issuerBaseURL: process.env.ISSUER_BASE_URL,
baseURL: process.env.BASE_URL,
clientID: process.env.CLIENT_ID,
secret: process.env.SECRET,
}
app.use(auth(config))
app.get('/', (req, res) => {
res.send(req.oidc.isAuthenticated() ? 'Logged in. Welcome!' : 'Logged out. <a href="/login">Login?</a>')
})
app.listen(3000)
What was the rationale behind removing the automatic refresh feature? Is there a recommended approach to automatically refreshing sessions if the access-token has expired?
Thanks in advance!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.