Auth0 Home Blog Docs

Implementing API keys by changing expiration using rule doesn't work any more

rules
authentication
api-keys
authorization
expire

#1

We are using a Rule to change the token expiration date in some cases by modifying jwtConfiguration.lifetimeInSeconds:

function (user, context, callback) {
  //When the api keys are requested;
  if(context.request.query.scope.indexOf('api_keys') > -1 ){
    Date.prototype.addYears=function(years) {
     return new Date(this.getTime() + years*31556926000); //milliseconds in a year
    };
    var d = new Date();
    var t = d.addYears(20);
    context.jwtConfiguration = context.jwtConfiguration || {};
    context.jwtConfiguration.lifetimeInSeconds = (t.getTime() / 1000);
    //Adding the jti
    var gen_jti = require('uuid').v4();
    console.log('requested api token transaction '+ gen_jti);
    user.jti = gen_jti;
  }
  callback(null, user, context);
}

It seems that this doesn’t work any more. The rule gets called and runs, but the expiration of the token doesn’t change. We think it stopped working around December 2016.

The reason why we do this is to implement API keys for our REST API. Back in February 2016 we asked Auth0 Customer Support and one of the engineers suggested this solution, which worked very well… while it worked :’(

A bit more about our use case:

We have a web application and a REST API. For the web application with use Auth0 for authentication. For the API, we generate JWT tokens using Auth0 which don’t expire (well, they expire in 20 years), and give those to our users so they can call our API endpoints. They do this the same way as in the web application, adding an “Authorization” header containing the JWT token (“Bearer xxx”).

The way that we ask Auth0 to generate these tokens is by passing a special scope (we call it “api_keys”), and then in the rule, if we have such a request we modify the expiration as shown above.

We just noticed that this broke, which for us means our API key mechanism is broken.

I read somewhere that you are not supporting jwtConfiguration.lifetimeInSeconds in some endpoints. Are you not going to support jwtConfiguration.lifetimeInSeconds any more?

Also, is there any other way to request tokens to Auth0 changing the expiration date? The normal expiration that we set in the Auth0 client is ok for the web application, but for API keys this is not a good option. Should we generate a separate client for this?

In general, how do you recommend your (Auth0) customers to proceed when they have their own REST API and they want to perform authentication using Auth0?


#2

In relation to support for jwtConfiguration.lifetimeInSeconds across all the authentication endpoints I don’t have more information to share besides the one already available in a related question.

In addition, at this point, the configuration of token expiration is either done at the client-level or API-level depending on who the token is for. (ID token expiration at the client-level, access token expiration at the API-level).


For the scenario you have described I would also take in consideration the following. Configure your API in the API section of your Dashboard and send JWT access tokens as the means to authorize the requests. Given that the setting you mentioned controlled the expiration of the JWT ID token I’m assuming you’re sending the ID token as the means to validate the API request. In general this is wrong as you should be sending an access token and not an ID token.

If you want to then issue traditional API Keys that provide access to an API and serve mostly to know who’s calling so that you know who to address the bill associated with API usage then go with client credentials. Every user/consumer of your API would be issued a set of client credentials that they could use to exchange for access tokens valid to call the API (you would create a non-interactive client in your Dashboard for each consumer and configure it to access the API in question).

Have in mind that, by default, there is no notion of end-users with client credentials. This is good when you want to give access to the API to a given customer, but don’t really care how many individual users/apps within that customer actually call into your API (it’s a perfect answer to the API usage billing as the more calls the more you charge).

If you’re giving these long-lived tokens because the API needs to always be called in the context of an end-user account then client credentials may not apply. If that’s the case the right solutions highly depends on the exact details; for example, it could be feasible for the API to accept the end-users credentials through HTTP basic authentication and then validate them by performing a resource owner password credentials grant.


#3

Ok, it’s complicated, but I’m trying to understand all this.

One question. When setting up an API, there are examples in three programming languages (PHP, node, C#). How would I do it in Java? And actually what does this code do? It verifies the access token? But in that case, I don’t see any secret keys or anything in the code, so how does it verify it?

Thanks!
Flavia


#4

Ok, it’s complicated, but I’m trying to understand all this.

One question. When setting up an API, there are examples in three programming languages (PHP, node, C#). How would I do it in Java? And actually what does this code do? It verifies the access token? But in that case, I don’t see any secret keys or anything in the code, so how does it verify it?

Thanks!
Flavia


#5

The quickstart example on the API section itself imply that the API uses RS256 as the signing algorithm. With RS256 there’s a private key used to create/issue tokens and a public key used to validate them; given the key used for validation can’t be used for creation then this key can be made available publicly. What those example do is retrieve that public key automatically from a know location based on the issuer (your Auth0 account in this case). They then validate the token with that key. For Java, there’s an API quickstart.


#6

Thank you @jmangelo ! I’ll try this.


#7

Thank you @jmangelo ! I’ll try this.


#8