Securing your application
To use Spring Security with a Single Web Page Application, like the ones generated by JHipster, you need Ajax login/logout/error views. We have configured Spring Security in order to use those views correctly, and of course we generate all the JavaScript and HTML code for you.
By default, JHipster comes with 4 different users:
- “system”, who is mainly used by our audit logs, when something is done automatically
- “anonymousUser”, who is given to anonymous users when they do an action
- “user”, who is a normal user with “ROLE_USER” authorization. His default password is “user”
- “admin”, who is an admin user with “ROLE_USER” and “ROLE_ADMIN” authorizations. His default password is “admin”
For security reasons, you should change those default passwords in production.
JHipster provides 4 main security mechanisms:
- JSON Web Tokens (JWT)
- Session-based authentication
- OAuth2 and OpenID Connect
- JHipster User Account and Authentication (UAA) (which has a separate documentation page as this is more complex)
JSON Web Tokens (JWT)
JSON Web Token (JWT) authentication is a stateless security mechanism, so it’s a good option if you want to scale your application on several different servers.
Please note that this is the default option when using a microservices architecture.
This authentication mechanism doesn’t exist by default with Spring Security, it’s a JHipster-specific integration of the Java JWT project.
This solution uses a secure token that holds the user’s login name and authorities. As the token is signed, it cannot be altered by a user.
Securing JWT
- The secret key is configured in the
application.yml
file, as thejhipster.security.authentication.jwt.secret
property. As this key must be kept secret, you should store it in a secure way for your production profile. It can be set up using the usual Spring Boot property configuration: using a Spring Cloud Config server like the JHipster Registry (our recommended option), using an environment variable, or even a specificapplication-prod.yml
file which is SCP’d by a sysadmin into the same directory as your application’s executable WAR file. - You should change the default “user” and “admin” passwords. The easiest way to do this is to deploy your application, login as “user/user” and then “admin/admin”, and for each of them use the “Account > Password” menu to change the password.
Session-based authentication
This is the “classical” Spring Security authentication mechanism, but we have improved it quite significantly. It uses the HTTP Session, so it is a stateful mechanism: if you plan to scale your application on multiple servers, you need to have a load balancer with sticky sessions so that each user stays on the same server.
Securing Session-based authentication
- For remember-me authentication, the remember-me key is configured in the
application-dev.yml
andapplication-prod.yml
files, as thejhipster.security.remember-me.key
property. As this key must be kept secret, you should store it in a secure way for your production profile. It can be set up using the usual Spring Boot property configuration: using a Spring Cloud Config server like the JHipster Registry (our recommended option), using an environment variable, or even a specificapplication-prod.yml
file which is SCP’d by a sysadmin into the same directory as your application’s executable WAR file. - You should change the default “user” and “admin” passwords. The easiest way to do this is to deploy your application, login as “user/user” and then “admin/admin”, and for each of them use the “Account > Password” menu to change the password.
Improved remember-me mechanism
We have modified the Spring Security remember-me mechanism so that you have a unique token, that is stored in your database (SQL or NoSQL database, depending on your choice during generation!). We also store more information than the standard implementation, so you have a better understanding of where those tokens come from: IP address, browser, date… And we generate a complete administration screen, so that you can invalidate sessions, for example if you forgot to log out on another computer.
Cookie theft protection
We have added a very complete cookie theft protection mechanism: we store your security information in a cookie, as well as in the database, and each time a user logs in we modify those values and check if they have been altered. That way, if a user ever steals your cookie, he will be able to use only once, at most.
CSRF protection
Spring Security and Angular both have CSRF protection out-of-the-box, but unfortunately they don’t use the same cookies or HTTP headers! In practice, you have in fact no protection at all for CSRF attacks. Of course, we re-configure both tools so that they correctly work together.
OAuth2 and OpenID Connect
OAuth is a stateful security mechanism, like HTTP Session. Spring Security provides OAuth 2.0 support, and this is leveraged by JHipster with its @EnableOAuth2Sso
annotation. If you’re not sure what OAuth and OpenID Connect (OIDC) are, please see What the Heck is OAuth?
Keycloak
Keycloak is the default OpenID Connect server configured with JHipster.
To log into your application, you’ll need to have Keycloak up and running. The JHipster Team has created a Docker container for you that has the default users and roles. Start Keycloak using the following command.
docker-compose -f src/main/docker/keycloak.yml up
If you want to use Keycloak with Docker Compose, be sure to read our Docker Compose documentation, and configure correctly your /etc/hosts
for Keycloak.
The security settings in src/main/resources/application.yml
are configured for this image.
security:
basic:
enabled: false
oauth2:
client:
access-token-uri: http://localhost:9080/auth/realms/jhipster/protocol/openid-connect/token
user-authorization-uri: http://localhost:9080/auth/realms/jhipster/protocol/openid-connect/auth
client-id: web_app
client-secret: web_app
scope: openid profile email
resource:
user-info-uri: http://localhost:9080/auth/realms/jhipster/protocol/openid-connect/userinfo
As by default Keycloak uses an embedded H2 database, you will lose the created users if you restart your Docker container. To keep your data, please read the Keycloak Docker documentation. One solution, with keeping the H2 database, is to do the following:
- Add a volume that will be persisted:
./keycloak-db:/opt/jboss/keycloak/standalone/data
- Change the migration strategy from
OVERWRITE_EXISTING
, toIGNORE_EXISTING
(in the command section)
Okta
If you’d like to use Okta instead of Keycloak, you’ll need to change a few things. First, you’ll need to create a free developer account at https://developer.okta.com/signup/. After doing so, you’ll get your own Okta domain, that has a name like https://dev-123456.oktapreview.com
.
Modify src/main/resources/application.yml
to use your Okta settings. Hint: replace {yourOktaDomain}
with your org’s name (e.g., dev-123456.oktapreview
).
security:
basic:
enabled: false
oauth2:
client:
access-token-uri: https://{yourOktaDomain}.com/oauth2/default/v1/token
user-authorization-uri: https://{yourOktaDomain}.com/oauth2/default/v1/authorize
client-id: {client-id}
client-secret: {client-secret}
scope: openid profile email
resource:
user-info-uri: https://{yourOktaDomain}.com/oauth2/default/v1/userinfo
Create an OIDC App in Okta to get a {client-id}
and {client-secret}
. To do this, log in to your Okta Developer account and navigate to Applications > Add Application. Click Web and click the Next button. Give the app a name you’ll remember, and specify http://localhost:8080
as a Base URI and http://localhost:8080/login
as a Login Redirect URI. Click Done and copy the client ID and secret into your application.yml
file.
Create a ROLE_ADMIN
and ROLE_USER
group (Users > Groups > Add Group) and add users to them. You can use the account you signed up with, or create a new user (Users > Add Person). Navigate to API > Authorization Servers, click the Authorization Servers tab and edit the default one. Click the Claims tab and Add Claim. Name it “groups” or “roles”, and include it in the ID Token. Set the value type to “Groups” and set the filter to be a Regex of .*
.
NOTE: If you want to use Okta all the time (instead of Keycloak), modify JHipster’s Protractor tests to use this account when running. Do this by changing the credentials in src/test/javascript/e2e/account/account.spec.ts
and src/test/javascript/e2e/admin/administration.spec.ts
.
After making these changes, you should be good to go! If you have any issues, please post them to Stack Overflow. Make sure to tag your question with “jhipster” and “okta”.
You can also use environment variables to override the defaults. For example:
export SECURITY_OAUTH2_CLIENT_ACCESS_TOKEN_URI="https://{yourOktaDomain}.com/oauth2/default/v1/token"
export SECURITY_OAUTH2_CLIENT_USER_AUTHORIZATION_URI="https://{yourOktaDomain}.com/oauth2/default/v1/authorize"
export SECURITY_OAUTH2_RESOURCE_USER_INFO_URI="https://{yourOktaDomain}.com/oauth2/default/v1/userinfo"
export SECURITY_OAUTH2_CLIENT_CLIENT_ID="{client-id}"
export SECURITY_OAUTH2_CLIENT_CLIENT_SECRET="{client-secret}"
You can put this in an ~/.okta.env
file and run source ~/.okta.env
to override Keycloak with Okta.
You can use then set these properties when you deploy to Heroku:
heroku config:set \
SECURITY_OAUTH2_CLIENT_ACCESS_TOKEN_URI="$SECURITY_OAUTH2_CLIENT_ACCESS_TOKEN_URI" \
SECURITY_OAUTH2_CLIENT_USER_AUTHORIZATION_URI="$SECURITY_OAUTH2_CLIENT_USER_AUTHORIZATION_URI" \
SECURITY_OAUTH2_RESOURCE_USER_INFO_URI="$SECURITY_OAUTH2_RESOURCE_USER_INFO_URI" \
SECURITY_OAUTH2_CLIENT_CLIENT_ID="$SECURITY_OAUTH2_CLIENT_CLIENT_ID" \
SECURITY_OAUTH2_CLIENT_CLIENT_SECRET="$SECURITY_OAUTH2_CLIENT_CLIENT_SECRET"
For Cloud Foundry, you can use something like the following, where $appName
is the name of your app.
cf set-env $appName SECURITY_OAUTH2_CLIENT_ACCESS_TOKEN_URI "$SECURITY_OAUTH2_CLIENT_ACCESS_TOKEN_URI"
cf set-env $appName SECURITY_OAUTH2_CLIENT_USER_AUTHORIZATION_URI "$SECURITY_OAUTH2_CLIENT_USER_AUTHORIZATION_URI"
cf set-env $appName SECURITY_OAUTH2_RESOURCE_USER_INFO_URI "$SECURITY_OAUTH2_RESOURCE_USER_INFO_URI"
cf set-env $appName SECURITY_OAUTH2_CLIENT_CLIENT_ID "$SECURITY_OAUTH2_CLIENT_CLIENT_ID"
cf set-env $appName SECURITY_OAUTH2_CLIENT_CLIENT_SECRET "$SECURITY_OAUTH2_CLIENT_CLIENT_SECRET"
See Use OpenID Connect Support with JHipster to learn more about JHipster and OIDC with Okta.
HTTPS
You can enforce the use of HTTPS when your app is running on Heroku by adding the following configuration to your SecurityConfiguration.java
.
@Configuration
public class WebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.requiresChannel()
.requestMatchers(r -> r.getHeader("X-Forwarded-Proto") != null)
.requiresSecure();
}
}
This will work on both Heroku and Cloud Foundry. For more production tips on Heroku, see Preparing a Spring Boot App for Production on Heroku.