I'm setting up a server with expressjs and keycloak-nodejs-connect, they are linked between them over common Storage for sessions. This works fine, ie, the flow with keycloak authentication its ok.
Now, I'm setting up a MQTT broker (Aedes) over server from expressjs. The unique authentication method in MQTT is username/password, then, I'm thinking about send the "token" (1) from webclient in the mqtt client connection flow in order to check on backend with keycloak-connect-nodejs if this token is valid.
I'm searching for some days and I cannot found a solution for this. How can i do? ie, verify the username received in the connection process on mqtt broker aginst keycloak over keycloak-connect-nodejs.
Or ... ¿are there other way to "link" mqtt authentication with my keycloak-session or express-session?
Thank you in advance.
(1) Which token should I use? From client I with keycloak.js I have the following token availables: idToken, token, subject, sessionId
Edit/Update with a solution
Several days later from starting my investigation, I have found the solution, my problem was that I'm trying authenticate into introspection endpoint with the accessToken, and I should do it with basic auth: client_name and client_secret. I have found the solution here: https://lists.jboss.org/pipermail/keycloak-user/2016-April/005869.html
Related
I'm trying to set up a frontend React app service and a backend Node app service, which both require authentication, according to this tutorial.
I've followed the steps except that I needed to set "loginParameters": ["response_type=code id_token", "scope=openid api://<backend app id>/user_impersonation"] instead of additionalLoginParams since my app uses auth v2.
When my frontend app calls my backend api I get the following error
{"code":401,"message":"IDX10205: Issuer validation failed. Issuer: '[PII is hidden]'. Did not match: validationParameters.ValidIssuer: '[PII is hidden]' or validationParameters.ValidIssuers: '[PII is hidden]'."}
I don't know how to debug this as the useful information in the response is hidded and I can't find a way to show it when using Node. I have inspected the token and the issuer is https://sts.windows.net/<tenant id>/, but I don't know what's expected or how to set ValidIssuer.
What I do for authentication code-wise is calling /.auth/me from frontend after login to receive an access token and this token is passed to the backend api in the header as Authentication: Bearer <access_token>. I'm expecting Azure to handle everything else according to the settings made in the linked tutorial. Is this correct?
How can I debug this issue?
EDIT
This is how the Expose an API page of backend app registration looks.
This is the data of my access token.
Your question has been resolved, post it as the answer to the end of the question.
As I said in the comments, you need to obtain the 2.0 version of the token. So you need to change the accessTokenAcceptedVersion attribute of the application manifest to: "accessTokenAcceptedVersion": 2.
We have an authenticated HTTP cloud function (CF). The endpoint for this CF is public but because it is authenticated, it requires a valid identity token (id_token) to be added to the Authorization header.
We have another Node JS application that is deployed in the same Google Cloud. What we want is to call the CF from the Node application, for which we will be needing a valid id token.
The GCP documentation for authentication is too generic and does not have anything for such kind of scenario.
So what is the best way to achieve this?
Note
Like every google Kubernetes deployment, the node application has a service account attached to it which already has cloud function invoker access.
Follow Up
Before posting the question here I had already followed the same approach as #guillaume mentioned in his answer.
In my current code, I am hitting the metadata server from the Node JS application to get an id_token, and then I am sending the id_token in a header Authorization: 'Bearer [id_token]' to the CF HTTP request.
However, I am getting a 403 forbidden when I do that. I am not sure why??
I can verify the id_token fetched from the metadata server with the following endpoint.
https://www.googleapis.com/oauth2/v1/tokeninfo?id_token=[id_token]
It's a valid one.
And it has the following fields.
Decoding the id_token in https://jwt.io/ shows the same field in the payload.
{
"issued_to": "XXX",
"audience": "[CLOUD_FUNTION_URL]",
"user_id": "XXX",
"expires_in": 3570,
"issuer": "https://accounts.google.com",
"issued_at": 1610010647
}
There is no service account email field!
You have what you need in the documentation but I agree, it's not clear. It's named function-to-function authentication.
In fact, because the metadata server is deployed on each computes element on Google Cloud, you can reuse this solution everywhere (or almost everywhere! You can't generate an id_token on Cloud Build, I wrote an article and a workaround on this)
This article provides also a great workaround for local testing (because you don't have metadata server on your computer!)
From what I understand about Socket.io, there are multiple security issues, such as those mentioned in this stack exchange post.
For my case, I'm using socket.io in Node and socket.io-client for React, and setting up a nice line of communication, however I don't need any login from the client side, since I'm simply querying an external API from the backend and posting results to the front end. So I've decided to use the package socketio-jwt to secure the connection using jwt tokens.
To implement, the documentation contains the following example to use jwt authentication:
Server Side
io.use(socketioJwt.authorize({
secret: 'your secret or public key',
handshake: true
}));
io.on('connection', (socket) => {
console.log('hello!', socket.decoded_token.name);
});
Client Side
const socket = io.connect('http://localhost:9000', {
extraHeaders: { Authorization: `Bearer ${your_jwt}` }
});
My question is this: on the client side where does the variable your_jwt come from and how can I generate it?
The token needs to be generated by the login API. The user sends username and password to a login endpoint and then your server returns the JWT.
Now, what is this login API?
Most API server implements an HTTP endpoint (POST /login). Then the client can save it in local storage.
If your app doesn't have an HTTP server to support you can just implement this via WebSocket.
You should have an endpoint in your Node app where you generate JWT, client side will get it from that endpoint, save it in persistent storage and reuse it.
I'm using AppAuth to authenticate users via OpenId Connect but I'm unable to get passport to respond, let along validate the token.
These are the endpoints given at accounts.google.com/.well-known/openid-configuration:
authorization_endpoint "https://accounts.google.com/o/oauth2/v2/auth"
token_endpoint "https://oauth2.googleapis.com/token"
passport-google-oauth20 defaults to
https://accounts.google.com/o/oauth2/v2/auth
https://www.googleapis.com/oauth2/v4/token
I have an id_token and I've verified it's working at https://oauth2.googleapis.com/tokeninfo?id_token=XYZ.
https://www.googleapis.com/oauth2/v4/token?id_token=XYZ gives an empty response.
I've been trying combinations of passport-google-oauth, passport-oauth2, passport-google-oauth, these various google apis(did i mention https://openidconnect.googleapis.com/v1 etc?), and various headers(JWT, Bearer, etc) and POST params. In every case passport's strategy just silently fails.
I've tried adding some debug info via middleware as described here:
https://dmitryrogozhny.com/blog/easy-way-to-debug-passport-authentication-in-express
It doesn't help.
For the love of god, I've been bashing against this for 48 hours. Someone please help!!!
I am using adal-node package in my Nodejs app for authenticating against Azure AD.
URL: https://www.npmjs.org/package/adal-node
I am using acquireTokenWithAuthorizationCode method to get the token and it works fine.
When my auth code expires, I want to refresh my token using the below.
authenticationContext.acquireTokenWithRefreshToken(_tokenData.refreshToken, authdata.clientId, authdata.resource, callback).
But when I run this code, its giving me the below error.
"Get Token request returned http error: 400 and server response: {"error":"invalid_request","error_description":"AADSTS90014: The request body must contain the following parameter: 'client_secret or client_assertion'
The method will not accept client secret as its argument, but still it complains that it needs a client secret.
Can you please help?
Thanks
Anil
Unfortunately, the library does not support your scenario right now. The function acquireTokenWithRefreshToken that you are using was intended for OAuth public clients that don't require a client secret, but your app is an OAuth confidential client which does.
I have filed the following issue in the GitHub repo to track the need to add a new method that would support your scenario.
https://github.com/AzureAD/azure-activedirectory-library-for-nodejs/issues/22