I want to get the Auth0 bearer token for my node.js app.
I got the bearer token by doing this:
curl https://myproject.eu.auth0.com/oauth/token --data "client_id=ID&client_secret=SECRET&type=web_server&grant_type=client_credentials"
Which returned me:
{
"access_token": *BEARER TOKEN*,
"token_type": "Bearer"
}
Though, if I use that token with postman in the Auth header, it tells me:
Invalid token. So how do I get the correct bearer token then?
My server looks like that:
const koa = require('koa');
const route = require('koa-route');
const jwt = require('koa-jwt');
const testRoute = require('./testRoute');
const app = koa();
//Copy pasted those values from my auth0 dashboard
const authentication = jwt({
secret: new Buffer(*CLIENT_SECRET*, 'base64'),
audience: *YOUR_CLIENT_ID*
});
app.use(authentication);
app.use(route.get('/test', testRoute));
app.listen(3000);
I followed this guide to set it up: https://auth0.com/docs/quickstart/backend/nodejs/.
The access_token is an opaque token, not a JWT which your application is expecting. If you use scope=openid when making the call to /oauth/token you'll get back an id_token as well, which is a JWT that your API should accept.
You can read more about how the scope parameter works in the context of Auth0 here: https://auth0.com/docs/scopes
Related
Keycloak 17.0.1
I have 2 tokens, one obtained via the JavaScript adapter and the other via java adapter. They are pretty much the same through jwt.io (same aud, azp...). I see the most significant difference is that the JavaScript token has "scope": "openid profile email", while the java token has "scope": "profile email" (without openid)
JavaScript token obtained by:
const keycloak = new Keycloak(
{url: 'http://keycloak-server$', realm: 'myrealm', clientId: '**frontend-app**' });
keycloak.init({ onLoad: 'login-required' })
//and get token from the property "token" of keycloak object.
Java token obtained by:
credentials = new HashMap<>();
credentials.put("secret", ""); //empty secret (this is a public frontend client)
config = new Configuration(url, realmName, "frontend-app", credentials, null);
authzClient = AuthzClient.create(config);
token = authzClient.obtainAccessToken("username", "1234").getToken();
Two tokens are given to server code, which is with the Java adapter:
credentials = new HashMap<>();
credentials.put("secret", "xxx"); //confidential backend-app client
config = new Configuration(url, realmName, "backend-app", credentials, null);
authzClient = AuthzClient.create(config);
request = new AuthorizationRequest();
request.addPermission("resourceid", {});
authzClient.authorization(token).authorize(request);
Two different results:
With token obtained by Java adapter: permission allowed
With token obtained by JavaScript adapter:
Got response: "error":"invalid_grant","error_description":"Invalid bearer token"},
And in KeyCloak log: type=PERMISSION_TOKEN_ERROR, realmId=xxx, clientId=xxx, userId=null, ipAddress=192.168.120.196, error=invalid_token, auth_method=oauth_credentials, grant_type=urn:ietf:params:oauth:grant-type:uma-ticket
I need to fix the Javascript client to work. Any help, please?
Thank you,
Huy Banh.
I have implemented the following code in my plain JavaScript webpage:
const http = new XMLHttpRequest()
http.open("GET", "<CognitoPoolDomainName>.auth.eu-central-1.amazoncognito.com/oauth2/userInfo");
http.setRequestHeader("Authorization", "Bearer " + jwtToken);
http.send();
http.onload = () => console.log(http.responseText);
});
the jwt token can be decrypt well in https://jwt.io/.
But I am getting this error message:
{"error":"invalid_token","error_description":"Access token is used against invalid domain"}
Can you help me tin understand what token - in which format - is required by this API Endpoint?
https://docs.aws.amazon.com/cognito/latest/developerguide/userinfo-endpoint.html
Many thanks!
I'm using Bitbucket Connect App and getting JWT token from webhook event.
When I am using the latest JWT to get access token, the access token API returning blank in response.
API:
curl -X POST -H "Authorization: JWT {jwt_token}" \ https://bitbucket.org/site/oauth2/access_token \ -d grant_type=urn:bitbucket:oauth2:jwt
Example:
curl -X POST -H "Authorization: JWT ey*****XVCJ9.eyJpc3MiOi****asdfQ.**BBD**" \
https://bitbucket.org/site/oauth2/access_token \
-d grant_type=urn:bitbucket:oauth2:jwt
Response
{blank}
API Reference:
https://developer.atlassian.com/cloud/bitbucket/oauth-2/
Thanks
I had the same problem until I added the sub key to the payload. Set the value to the value received in clientKey during the app installation lifeycle event.
I followed this documentation to generate Access Token and it worked.
https://pawelniewiadomski.com/2016/06/06/building-bitbucket-add-on-in-rails-part-7/
Most of the Part for generating access token using Bitbucket Cloud API
def get_access_token
unless current_jwt_auth
raise 'Missing Authentication context'
end
# Expiry for the JWT token is 3 minutes from now
issued_at = Time.now.utc.to_i
expires_at = issued_at + 180
jwt = JWT.encode({
iat: issued_at,
exp: expires_at,
iss: current_jwt_auth.addon_key,
sub: current_jwt_auth.client_key
}, current_jwt_auth.shared_secret)
response = HTTParty.post("#{current_jwt_auth.base_url}/site/oauth2/access_token", {
body: {grant_type: 'urn:bitbucket:oauth2:jwt'},
headers: {
'Content-Type' => 'application/x-www-form-urlencoded',
'Authorization' => 'JWT ' + jwt
}
})
if response.code == 200
Response.new(200, response.parsed_response)
else
Response.new(response.code)
end
end
I am using JWT token based authentication system. i.e djangorestframework-simplejwt in my backend
Now I am using reactj and axios as frontend:
After providing username and pass to the login api, I got access_token and refresh_token which I stored in the localstorage
Now I am trying to connect to an api using access_token.
I get Token invalid or expired
Example I am trying to change password using this api and provide access_token
const url = "dj-rest-auth/password/change/";
const auth = {
headers: {
Authorization: "Bearer " + localStorage.getItem("access_token"),
Accept: "application/json",
"Content-Type": "application/json",
},
};
const data = {
old_password: old_password,
new_password1: new_password1,
new_password2: new_password2,
};
const promise = axios.post(url, data, auth);
promise
.then((res) => {
console.log(res)
})
.catch((err) => {
if (err.response) {
console.log(`${err.response.status} :: ${err.response.statusText}`)
console.log(err.response.data)
}
})
I can do another api call using refresh_token to get access_token when i get an err.
But sometimes, the err can be due to network error or something else. Then even i try to get access_token using refresh_token, it will just get into a loop.
HOw to do this the right way
If you are using Django as the backend, I would suggest using dj-rest-auth for JWT token authentication. dj-rest-auth requires "djangorestframework-simplejwt" for token management.
It is recommended to store access token and refresh token in httponly cookie so that it is not accessed by javascript.
Add JWTtokenAuthentication as authentication classes in settings.py.
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'dj_rest_auth.jwt_auth.JWTCookieAuthentication'
]
}
Add the below configuration too in settings.py
REST_SESSION_LOGIN = False
SITE_ID=1
REST_USE_JWT = True
JWT_AUTH_COOKIE = 'access-token' #any name
JWT_AUTH_REFRESH_COOKIE = 'refresh_token' #any name
JWT_AUTH_SECURE = True
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
There is an open issue with dj-rest-auth, that requires the below code to be implemented in your back-end Github issue: https://github.com/iMerica/dj-rest-auth/issues/97. As workaround suggested, you have to create a file middleware.py and paste below code.
import json
from django.utils.deprecation import MiddlewareMixin
from yourapp.settings import JWT_AUTH_REFRESH_COOKIE # from settings.py
class MoveJWTRefreshCookieIntoTheBody(MiddlewareMixin):
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
return response
def process_view(self, request, view_func, *view_args, **view_kwargs):
if request.path == '/token/refresh/' and JWT_AUTH_REFRESH_COOKIE in request.COOKIES:
if request.body != b'':
data = json.loads(request.body)
data['refresh'] = request.COOKIES[JWT_AUTH_REFRESH_COOKIE]
request._body = json.dumps(data).encode('utf-8')
else:
print("The incoming request body must be set to an empty object.")
return None
By now, your back-end will be successfully generating access token and refresh token. Even your back-end will be capable of refreshing access token using refresh token.
Front-End:
By default, access token and refresh tokens are stored in httponly cookie, so you don't need to worry about that part.
Axios can be used to make call to login-end point to get tokens. Make sure you use "withCredentials" and "Headers" in your request.
Response will be tokens, by default it will be stored in httponly cookie, since we are using dj-rest-auth. For all the consecutive requests, httponly cookie will be included, if tokens are valid, user will be provided access. IF token is expired, you need to make call to refresh endpoint to get new access token.
Since you are in development mode, you have to have same domain for both BE and FE, different ports.You can start django-server using below command and make sure your FE is also running in localhost
python manage.py runserver localhost:8080
dj-rest-auth : https://dj-rest-auth.readthedocs.io/en/latest/index.html
I'm using JWT verification with PostGraphile 4.6.0 in a node project. Here is the the code snippet:
createServer(
postgraphile(env.DATABASE_URL, "public", {
jwtVerifyAlgorithms: ["RS256"],
jwtSecret: "./publickey.pem",
jwtPgTypeIdentifier: "public.jwt_token",
rejectUnauthorized: false,
graphiql: true,
enhanceGraphiql: true,
graphqlRoute: env.POSTGRAPHILE_ROUTE + "/graphql",
graphiqlRoute: env.POSTGRAPHILE_ROUTE + "/graphiql",
})).listen(port, () => {
console.log("Listening at port:" + port);});
But when I use Postman to send RS256 encrypted JWT token, get error:
{
"errors": [
{
"message": "invalid algorithm"
}
]
}
And I created a function in Postgres to return JWT token, it always return HS256 encrypted JWT token. And I I use PostGraphile returned HS256 encrypted JWT token in Postman, JWT token is validated and the GrqphQL query returns fine.
Appears that the option "jwtVerifyAlgorithms" doesn't take effect.
Is there a way to make this work for RS256 encrypted JWT token?
Set the sign algorithm in jwtSignOptions
The following configuration should work:
{
...
jwtPublicKey: fs.readFileSync(process.env.PUBLIC_KEY_FILE_PATH, 'ascii'),
jwtSecret: fs.readFileSync(process.env.SECRET_KEY_FILE_PATH, 'ascii'),
jwtSignOptions: { algorithm: 'RS256' },
jwtTokenIdentifier: 'foo.bar',
jwtVerifyAlgorithms: ['RS256'],
...
}
The Postgraphile documentation states jwtPublicKey as the correct setting for providing the keys. Right now you are using jwtSecret with the string "./publickey.pem" which will not load the file, but instead use the file path as a password.
Make sure to load the file yourself using something like this:
...
jwtPublicKey: fs.readFileSync("./publickey.pem", "ascii")
...
Alternative via pgSettings
Worst case scenario you can also provide a custom pgSettings function that uses the jsonwebtoken npm library and verify the token yourself and write it to your settings.