NextAuth - mocking OneLogin flow - javascript

I'm trying to setup a OneLogin mocked service locally using WireMock. So far so good, I was able to mock most of the OAuth OneLogin flow but I can't manage to solve the last part in order to get it working properly...
Whenever I submit credentials on my Mocked OneLogin page and it redirects me back to the application I get error: RPError: failed to validate JWT signature. From the debugging I discovered that the problem is in the mocked OneLogin server on the "jwks_uri": "http://localhost:27442/oidc/2/certs" endpoint. Seems the last part of NextAuth verification which is using jose..compactVerify(jwt, key instanceof Uint8Array ? key : key.keyObject) doesn't match what I've mocked thus not allowing me to proceed with mocked login.
Does anyone know what should the /oidc/2/certs endpoint return to match generated mocked token??
How should the JWT and return value of oidc/2/certs look like to be approved.
I generated JWT on https://jwt.io/
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTY2NjAwMDgwMCwiZXhwIjoxNjY4Njc5MjAwLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjI3NDQyL29pZGMvMiIsImF1ZCI6InNvbWUtY2xpZW50LWlkIn0.QLqLlhoZi7JnqTAYibPkIFPvmC88t4Z7AbUspSX8ENbEnK0NXV_hTxAXLA3-V7TjuIWlrJOvOT7BrHP3N39XV0Vb5pw_X4OY48ce9JQR46x5v3YeU4wgm48sWCIkwRVNDGV0_oF1Pr2Qa4egAVDzLDxtoqrgV4W_wjOI-jxv2r0NWeNvgsSH68PC0qTcgfuLG_k1Sf61CBS-_DKHGznD9gdHc3xJM2Rh3FLQQ5-JHVlE0nB0If8Gx-Q5_cI2VQaDwj-x4VO9qzE2o1zes41NgyP1D85TODegPN6lNvpLMyexIBwl5LYP0WnpW9ZDKziUqVLkuJ4LTnl5jg9ZsbXQ2Q
and looking at onelogin docs I found this https://acme.onelogin.com/oidc/2/certs
How can I match above to be verified successfully? I basically want an infinite JWT (RS256 alg) token that will be verified mitigating OneLogin flow in development environment

After fighting with this for several days I found a solution.
I had to Generate JWT token with appropriate header and payload values on https://jwt.io/#debugger-io then copy public key and generate JWK with it on
https://russelldavies.github.io/jwk-creator/

Related

apple-signin-auth node js react native error: Invalid id token public key id

I have a React native front end where I use invertase/react-native-apple-authentication to handle Apple Authentication.
Then I have a NodeJS back end, where I use A-Tokyo/apple-signin-auth to handle Apple authenticated users and let them access routes.
I made this authentication based on this article.
I want the users to be able use the app without logging in again without a time limit.
Therefore I save the identity token, which I get when the user does the first sign up in Async Storage in the front-end. Every time the user tries to access routes the user will be checked if he/she has a identityToken in the Header in my isAuth middleware in the NodeJS backend for the respective request.
I can see in my logs not sometimes requests get the following error the backend in my isAuth middleware:
JsonWebTokenError: error in secret or public key callback: input error: Invalid id token public key id at /app/node_modules/jsonwebtoken/verify.js:96:19 at _getIdTokenApplePublicKey (/app/node_modules/apple-signin-auth/lib/index.js:1:5730) at runMicrotasks () at processTicksAndRejections (internal/process/task_queues.js:95:5)
The error is thrown in the apple-signin-auth library when executing this code:
const appleSignin = require("apple-signin-auth");
result = await appleSignin.verifyIdToken(token, {
audience: config.CLIENT_ID_APPLE,
ignoreExpiration: true, // ignore token expiry (never expires)
});
I am not sure why this is happening. When I check the tokens, they seem fine but expired. The CLIENT_ID is right 100%. Does it has something todo with the expiration of the token?
A list for valid options for the appleSignin.verifyIdToken function is stated here.
Thanks for the help!
What I found out is that the public keys from the apple endpoint: https://appleid.apple.com/auth/keys
are changing over time. The library is using those keys for decoding or validating the identityToken. As a result the key ids are not matching with the key id from the identity token I saved in the Async Storage. It cannot find the matching kid in the public keys because they are not there anymore. I am thinking about what solution to implement.
Possible solution: Instead of storing the IdentityToken, I should store the RefreshToken in the AsyncStorage in the front end. Hopefully that's a valid approach. (Token based authentication)
And then request a new IdentityToken with every back-end request in the isAuth Middleware with the RefreshToken (which according to Apple is endlessly valid).
Then verify the IdentityToken with the
appleSignin.verifyIdToken
method of apple-signin-auth package and give user access to route or not. The public keys from the Apple endpoint are always up-to-date, since the identity token is always requested again.
As far as I understand the workflow, you verify the identity token in the backend only once when the user has authenticated themselves using "Sign in with Apple" on the device.
If verifying the identity token in the backend was successful, you receive a refresh token in the response. You are then supposed to save this refresh token in your backend and verify the refresh token once a day to check if the user is still logged in with Apple. What does that mean? For example a user could revoke access to your app. Or a different user could log in on the Apple device.
By the way, if you verify the refresh token on every request (read multiple times a day), you risk Apple throttling these requests.
Bear in mind that this doesn't free your system from rolling its own session management meaning that your system sends its own session ids back and forth between the backend and front-end. Once a day, you check the refresh token associated with a session to see if the user is still logged in.
Disclaimer: This is how I understood the docs of Sign in with Apple. In other works, I have no experience implementing it. Hope it helps nonetheless.

How to generate new id tokens for custom backend with firebase auth?

We have built a custom nodejs backend but the authentication is using firebase auth with idtoken, the idtokens expire after 1 hour and the user is automatically logged out. When using firestore this is handled automatically, we have seen solutions that suggest a service worker but that has not worked.
Can someone please suggest a stable solution for this may be a middleware on the backend API's that can regenerate the tokens?
Thanks
The user is not logged out and that is why Firestore keeps working. You can use getIdToken() method again to get user's ID Token and then pass it in API request.
firebase.auth().currentUser.getIdToken(/* forceRefresh */ true).then(function(idToken) {
// Send token to your backend via HTTPS
// ...
}).catch(function(error) {
// Handle error
});
The normal approach (which the Firebase services themselves use too) is to always the current token with each request to the backend service, so that the service has at least 5m to complete the request (which is a lot more than most services need).
If you need a token that can be used for longer, you can consider forcing a refresh of the token before you call the service as Dharmaraj pointed out in their answer.
Alternative, you can switch to using session cookies for the user, which can have an expiration of up to two weeks.

AWS: Error when calling getCredentialsForIdentity()

I am trying to get a login procedure to work in AWS by following the Enhanced Authflow for Developer Authentication mentioned in the official documentation.
The code in both client and server are using JavaScript, and I'm using Node.js on the server-side.
I have managed to get the OpenId token back to the client but when I try to exchange it for credentials by calling getCredentialsForIdentity(), the client receives this error:
NotAuthorizedException: Access to Identity 'eu-west-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' is forbidden.
Also on the server-side when I print the variable holding my AWS.CognitoIdentity object and check the property cognitoidentity.config.credentialProvider all I get is:
{"providers":[null,null,null,null]}
It feels like the named custom developer provider I have associated with my identity pool should be in there but I seem to not be able to get it there.
Any thoughts on where I might have gone wrong?
That error is usually thrown when you try to get access to an authenticated id without providing any of the tokens linked to that identity. If it's an authenticated identity, make sure you are giving a token for it.

Testing parser for oauth2 implicit grant access_token in javascript

I'm writing angular application that uses implicit grant oauth strategy. If I don't have valid access token in my cookies I am redirected to web interface of authentication server, input my credentials and get redirected to my site with access token in the url. My system parses it and writes down into cookies.
Currently I faced question of unit testing this parse function that consumes the url and returns access token object. Can't think the good way, so writing here:
1. How do you approach unit testing (so I can't make direct request to working oauth server) a function that parses the access token from authentication server?
2. How do you build url params with access token? Will it be secure if I copy current access token and use it in test data?
3. Are there libraries that can aid creation of mock access token object?
You could breakout "just enough" OAuth, like the service linked below. This will give you a super-basic OAuth provider, but is really geared to "integration testing" scenarios (depending on where you draw the lines on these things).
If you want to be a unit-testing purist/zealot, then you could fork this into your app's unit test code.
https://github.com/zalando-stups/mocks/tree/master/oauth2-provider
In lieu of a great answer, here's one to get you out of a hole :)
After approaching authors of my oAuth authentification service I've got insight on the data the server was sending me in case of successful authentication. In my case the response from oAuth server has the following form:
header // encoded algorithm for has creation
access token // base64 encoded object
hash // of the 3 previous items done using algorithm specified in the header.
It has the following structure: header.access_token.hash
My fear for security breach was concerned about putting correct data (that I can get from browser) into the test files. But as it turns out the token will not be valid without correct hash. The hashing of the token data is done in server side using private key, so if I change the hash the token will become obsolete.
As my token-parsing-function that I wanted to check uses only the access_token part of the request, I've changed the header and hash parts and also encoded other user name for sake of testing purposes.
So this is the resolution of my current problem. Hope this will help somebody.

Authentication for a SPA and a node.js server

I have a very simple node.js app built on express which has been handling authentication using a session memory store. Basically a user logs in by:
app.post('/sessions', function(req, res) {
// check username/password and if valid set authenticated to true
if (authenticated){
req.session.user = req.body.username;
} ...
});
Then in each call from the browser a requiresLogin middleware function is called which checks to see if that user property on the session has been set.
I'm now transitioning the app to basically just provide a service that may or may not be consumed in the browser, so instead of using cookies/sessions, I'm considering changing the system so that one would post to /getToken (instead of /sessions) which would return a temporary random token associated with a user's account that could then be used for a period of time to access the service. Using the service would then require a valid token to be included in each call. (I assume this would be better than passing the username/password each time so that the password would not have to be stored in memory on the client's computer after the call to get token?)
Would such a system basically be just as secure as the above current system or Is there a much more standard/safe way to handle this? What's the standard way to handle something like this?
Thanks in advance for you help!
What you are looking for is called an HMAC and there is a great article here to get ideas on how to implement for your service.
As to whether session based security is more secure than public/private keypairs is widely debated and really depends on the implementation/application. In your case, since you want per request authentication on a public facing API, the HMAC is the way to go.

Categories

Resources