JWT Token could not be verifed before - jwt

I am currently using JWT since the past month and I had no issues. But since yesterday, I am experiencing this error as per below
com.auth0.jwt.exceptions.InvalidClaimException: The Token can't be used before...
I understand there is a timestamp when generating the token and the token cannot
be verified before that. The token is being verified on another server. But all this time, it was fine. Can someone advise?
Thanks,

If you are using auth0-spring-security-api then you can customize leeway as follow:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Value(value = "${auth0.audience}")
private String apiAudience;
#Value(value = "${auth0.issuer}")
private String issuer;
#Override
protected void configure(HttpSecurity http) throws Exception {
final JwkProvider jwkProvider = new JwkProviderBuilder(issuer).build();
JwtAuthenticationProvider jwtAuthenticationProvider = new JwtAuthenticationProvider(jwkProvider, issuer,
apiAudience);
jwtAuthenticationProvider.withJwtVerifierLeeway(3);
JwtWebSecurityConfigurer.forRS256(apiAudience, issuer, jwtAuthenticationProvider).configure(http)
.authorizeRequests().antMatchers("/**").authenticated();
}

Perhaps try viewing your JWT token using https://jwt.io/ - can you ascertain whether it has expired? Take the exp value (likely epoch) and convert - https://www.epochconverter.com/
You have added very little info in the question to offer any further details. You could try (re-) authenticating with the IDP that issued you the JWT token last time, and check whether that resolves your issue too.
Based on your last comment, do the servers have any clock skew?

First of all have a look at your AUTH provider tenant settings. If the Login Session Management -> Inactivity timeout is set to too low, try increasing it and see if the error is happening.
OR
try: https://auth0.com/docs/libraries/auth0js/v8

Related

Implementing a connection recreation mechanism on periodic DB password change

We are using a PostgreSQL database with AWS RDS IAM authorization feature – which means that our application needs to refresh the authorization token every 10 minutes or so (since the token is valid for 15 minutes). This token is used as a database password and I need to periodically update it. We are using the Dropwizard framework which is taking advantage of Apache Commons DBCP Component that handles connection pooling.
I was able to enhance the configuration class so that it performs an AWS API call to get the token instead of reading the password from configuration file. However this works only once, during application startup, for 15 minutes. I would like to call AWS API for the token perdiodically and handle the creation of connections as well as invalidating old ones.
import org.jooq.Configuration;
import org.jooq.impl.DefaultConfiguration;
import io.dropwizard.setup.Environment;
import org.example.myapp.ApplicationConfiguration;
// more less relevant imports...
#Override
public void run(ApplicationConfiguration configuration, Environment environment) {
Configuration postgresConfiguration = new DefaultConfiguration().set(configuration.getDbcp2Configuration()
.getDataSource())
.set(SQLDialect.POSTGRES_10)
.set(new Settings().withExecuteWithOptimisticLocking(true));
// this DSLContext object needs to be refreshed/recreated every 10 minutes with the new password!
KeysDAO.initialize(DSL.using(postgresConfiguration));
// rest of the app's config
}
How can I implement such a connection recreation mechanism? The org.jooq.ConnectionProvider looks promising, but I need some more guidance on how to inject the password on a periodic basis (and implement a custom ConnectionProvider). Any hints would be greatly appreciated.
EDIT:
This morning I was able to confirm that after a fresh deployment the database interaction is possible, and after exactly 15 minutes I'm getting first exceptions:
org.postgresql.util.PSQLException: FATAL: PAM authentication failed for user "jikg_service"
at org.postgresql.core.v3.ConnectionFactoryImpl.doAuthentication(ConnectionFactoryImpl.java:514)
at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:141)
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:192)
at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49)
at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:195)
at org.postgresql.Driver.makeConnection(Driver.java:454)
at org.postgresql.Driver.connect(Driver.java:256)
at org.apache.commons.dbcp2.DriverConnectionFactory.createConnection(DriverConnectionFactory.java:39)
at org.apache.commons.dbcp2.PoolableConnectionFactory.makeObject(PoolableConnectionFactory.java:256)
at org.apache.commons.pool2.impl.GenericObjectPool.create(GenericObjectPool.java:868)
at org.apache.commons.pool2.impl.GenericObjectPool.ensureIdle(GenericObjectPool.java:927)
at org.apache.commons.pool2.impl.GenericObjectPool.ensureMinIdle(GenericObjectPool.java:906)
at org.apache.commons.pool2.impl.BaseGenericObjectPool$Evictor.run(BaseGenericObjectPool.java:1046)
at java.base/java.util.TimerThread.mainLoop(Timer.java:556)
at java.base/java.util.TimerThread.run(Timer.java:506)
Suppressed: org.postgresql.util.PSQLException: FATAL: pg_hba.conf rejects connection for host "172.30.19.218", user "my_db_user", database "my_db_development", SSL off
at org.postgresql.core.v3.ConnectionFactoryImpl.doAuthentication(ConnectionFactoryImpl.java:514)
at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:141)
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:201)
... 12 common frames omitted
Those exceptions are repeated every minute.
I owe you all an explanation on this one. I forgot to mention one significant detail - we're actually using a modified version of Dropwizard developed in-house that uses bundled Apache Commons DBCP (which afaik is not officially part of Dropwizard) as well as other components. I ended up dropping Apache Commons DBCP in favor of HikariCP - which made it possible to update the pool configuration at runtime. Although not officially supported, the creator of the library hinted that it might work, and in our scenario it indeed worked. Below is a sample solution.
import org.jooq.Configuration;
import org.jooq.impl.DefaultConfiguration;
import io.dropwizard.setup.Environment;
import org.example.myapp.ApplicationConfiguration;
// more less relevant imports...
#Override
public void run(ApplicationConfiguration configuration, Environment environment) {
HikariDataSource hikariDataSource = loadDatabaseConfiguration(configuration.getDatabaseConfiguration());
new DbConfigurationLoader(hikariDataSource).start();
// this DSLContext object now has the reference to DataSource object that has an always-fresh password!
KeysDAO.initialize(DSL.using(hikariDataSource, SQLDialect.POSTGRES_10, new Settings().withExecuteWithOptimisticLocking(true)));
// rest of the app's config
}
private HikariDataSource loadDatabaseConfiguration(DatabaseConfiguration configuration) {
HikariDataSource hikariDataSource = new HikariDataSource();
hikariDataSource.setJdbcUrl(configuration.getJdbcUrl());
hikariDataSource.setDriverClassName(configuration.getDriverClassName());
hikariDataSource.setMinimumIdle(configuration.getMinimumIdle());
hikariDataSource.setMaximumPoolSize(configuration.getMaximumPoolSize());
hikariDataSource.setUsername(configuration.getJdbcUser());
return hikariDataSource;
}
private class DbConfigurationLoader extends Thread {
private final HikariDataSource hikariDataSource;
private final RdsTokenProvider rdsTokenProvider;
public DbConfigurationLoader(HikariDataSource hikariDataSource) {
this.rdsTokenProvider = new RdsTokenProvider();
this.hikariDataSource = hikariDataSource;
}
#Override
public void run() {
while (true) {
hikariDataSource.setPassword(rdsTokenProvider.getToken());
try {
Thread.sleep(/* token is valid for 15 minutes, so it makes sense to refresh it more often */);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
Hope this saves somebody some time in the future.

WSS4J SOAP Signature validation without truststore

I need to validate a signed SOAP message, extract the certificate and authenticate the certificate against a LDAP directory, which makes a trust store unnecessary. I have being using the WSS4J for a while now, but always with a local trust store. Taking a look on the official documentation and googling around, I couldn't find any reference to a scenario similar to mine. I was wondering if it would be possible to keep using the WSS4J in that case.
Yes you can use WSS4J for this use-case. WSS4J uses the SignatureTrustValidator by default to validate trust in signing certificates:
https://github.com/apache/ws-wss4j/blob/master/ws-security-dom/src/main/java/org/apache/wss4j/dom/validate/SignatureTrustValidator.java
You can plug your own implementation in there instead via:
https://github.com/apache/ws-wss4j/blob/66ab5fdbeeda0e0cbd6e317272dadd4417f6be91/ws-security-common/src/main/java/org/apache/wss4j/common/ConfigurationConstants.java#L863
If you are using CXF with WSS4J, there is a custom configuration constant that you can set that points to the Validator implementation for Signatures.
I faced the same problem and solved it in this way:
#EnableWs
#Configuration
public class WsConfiguration extends WsConfigurerAdapter {
#Bean
public Wss4jSecurityInterceptor securityInterceptor() throws Exception {
Wss4jSecurityInterceptor securityInterceptor = new Wss4jSecurityInterceptor();
securityInterceptor.setValidationActions("Signature");
WSSConfig wssConfig = WSSConfig.getNewInstance();
wssConfig.setValidator(new QName("http://www.w3.org/2000/09/xmldsig#", "Signature"), MySignatureTrustValidator.class);
securityInterceptor.setWssConfig(wssConfig);
//the rest of configuration
}
Note, that MySignatureTrustValidator must implement Validator

How can the resource server identify the resource owner using token in oauth2?

The typical scenario I am looking into is:
User1 provides proper credentials to the front-end rest client (grant type: password) and the client gets the token in return.
The client sends the token and accesses the resources owned by User1.
In my scenario, once the client has the access token for user1, I want the client to have access limited to User1's resources only.
Consider that the client accesses the URI /users/1/books. The response will contain all the books associated with User1. The main problem is that if the client accesses the URL /users/2/books with User1's token, it gets the list of all the books for User2 which shouldn't be allowed.
How can I limit the scope to the user whose credentials were used to obtain the token?
How can I map the token to a specific user in my resource server?
I am using Spring/Java. But any general theory will also help.
After a lot of debugging, I got the answer.
Spring security 1.4
Token store: InMemoryTokenStore()
In ResourceServerConfiguration, configure HttpSecurity.
#Override
public void configure(final HttpSecurity http) throws Exception {
// #formatter:off
http.authorizeRequests().
// antMatchers("/oauth/token").permitAll().
antMatchers("/api/users/{userId}").access("#webSecurity.checkUserId(authentication,#userId)")
.anyRequest().authenticated().and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().csrf().disable();
// #formatter:on
}
Create a class WebSecurity and provide the implementation.
public class WebSecurity {
public boolean checkUserId(Authentication auth, int id) {
return ((UmUser)auth.getPrincipal()).getId() == id;
}
}
Resources:
http://docs.spring.io/spring-security/site/docs/current/reference/html/el-access.html#el-access-web-path-variables
http://www.baeldung.com/get-user-in-spring-security
I had to debug a lot as I was using JwtTokenStore. This returned the Principal as a String and not the instance of UserDetails as I was expecting.
Once I switched to InMemoryTokenStore, I got the expected results. This was not a problem for me as I had the choice, but I would still like to know how to achieve it with the JWT.

Apache Shiro. 'Remember me' and cookies don't working

I am developing a vaadin-based project using Apache Shiro 1.2 for security. I have a problem with 'remember me' feature. I try to use CookieRememberMeManager as RememberMeManager, but after authentification Subject.isRemembered() always returns false.
public class ApplicationSecurityManager extends DefaultSecurityManager {
public ApplicationSecurityManager(Realm singleRealm) {
super(singleRealm);
setRememberMeManager(new CookieRememberMeManager());
}
}
I set SecurityManager in init method of GuiceFilter.
final Realm realm = new ApplicationSecurityRealm();
final SecurityManager securityManager = new ApplicationSecurityManager(realm);
SecurityUtils.setSecurityManager(securityManager);
When I try to login to my application, all works fine except 'remember me' feature.
Code:
final Subject currentUser = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username,password);
token.setRememberMe(rememberMe);
currentUser.login(token);
Application have no exceptions, and i could't resolve this problem using debug.
I use Apache Tomcat 7.0.40, can it to forbid cookies?
P.s. Sorry for my English, I'm not from an English-speaking country.
I realize it has been a year, but this question is getting a fair number of views, so I thought I'd post some information.
Subject.isRemembered() is a little tricky in Shiro. It only returns true if the Subject has a valid Remember Me setting (cookie, etc) AND the Subject is not Authenticated. Details here: http://shiro.apache.org/static/1.2.2/apidocs/org/apache/shiro/subject/Subject.html#isRemembered()
So, I suspect that your Remember Me is working fine, but your expectations for Subject.isRemembered() doesn't match what the method actually does.

Apache Shiro: How would you manage Users?

I want to use Shiro on my next web project but I do not know a good (if not the best) strategy to manage users ([users] in shiro.ini).
Is it best to create Shiro user for every registered member?
Or create a single Shiro user then for every member just store it to some database and acces it via that Shiro user?
If you would go for #1, how would you manage/automate it? Most of the projects I worked on opted for #2.
Thanks
Configuring users in shiro.ini is not a good option for production environment. It can be used only if you have a small number of user accounts and you don't need to create or change accounts at runtime. It is mostly used for testing.
It is better for almost all projects to use some storage to keep all user accounts. It can be database or some external authentication engine, like ldap, cas or even oauth.
You can just use Stormpath as your user/group store. Drop in the Shiro integration and boom - instant user/group data store for Shiro-enabled applications with a full management UI and Java SDK.
It even helps automate things like 'forgot password' emails and account email verification. It's free for many usages too. You can see the Shiro sample app using Stormpath as an example.
Shiro provides multiple ways to configure users. Take a look at the possible Realm configurations here.
If none of these satisfy your needs, you could even write a custom Realm for your application, that can, say, pull user info from a NoSQL database, or get info from a SAML response, or use OAuth2. It's definitely not advisable to create any user details in shiro.ini in production. To give a notion of what custom realms might look like, here's an example where I created a SAML2 based user authc and authz: shiro-saml2.
PLease do not use only one user for everyone. Avoid this option.
Much better to use one user(account) per user.
In shiro, you can have the RDMS Realm that allows you to use a simple database like mysql in order to store your user /account / permissions. :)
Clone this project, (that is not mine), and get started in 1 minute! :)
shiro/mysql GIT example
Enjoy it :)
Shiro provide implementing your own realm as per your requirement.
Create a simple realm in which you can manage details, login, permissions and roles.
You can use jdbc, Hibernate, or any other authentication manner to manage them.
Configure this realm to your ini or whatever way you using in your project.
Now Shiro will automatically invoke methods of your realm class to look for credential, permissions, roles.
For ex I have a shiro hibernate realm I used my hibernate code to manage users in my db.
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
/**
* #author Ankit
*
*/
public class PortalHibernateRealm extends AuthorizingRealm {
private static final Logger LOGGER = new Logger(
PortalHibernateRealm.class.toString());
/**
*
*/
public PortalHibernateRealm() {
super();
/*
* Set credential matcher on object creation
*/
setCredentialsMatcher(new CredentialsMatcher() {
#Override
public boolean doCredentialsMatch(AuthenticationToken arg0,
AuthenticationInfo arg1) {
UsernamePasswordToken token = (UsernamePasswordToken) arg0;
String username = token.getUsername();
String password = new String(token.getPassword());
/*
Check for credential and return true if found valid else false
*/
return false;
}
});
}
#Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principalCollection) {
Collection<String> permissionSet;
SimpleAuthorizationInfo info = null;
Long userId = (Long) principalCollection.getPrimaryPrincipal();
//Using thi principle create SimpleAuthorizationInfo and provide permissions and roles
info = new SimpleAuthorizationInfo();
return info;
}
#Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken authcToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
/*using this token create a SimpleAuthenticationInfo like
User user = UserUtil.findByEmail(token.getUsername());
*/
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
primaryPrin, Password, screenName);
return authenticationInfo;
}
}