Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade to Spring Security 5.1's OIDC Support #9416

Merged
merged 23 commits into from
Mar 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 0 additions & 15 deletions generators/client/files-react.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,20 +143,6 @@ const files = {
path: REACT_DIR,
templates: ['app.scss', '_bootstrap-variables.scss']
}
// {
// condition: generator => generator.authenticationType === 'oauth2' || generator.authenticationType === 'jwt' || generator.authenticationType === 'uaa',
// path: REACT_DIR,
// templates: [
// 'blocks/interceptor/_auth.interceptor.js'
// ]
// },
// {
// condition: generator => !generator.skipServer,
// path: REACT_DIR,
// templates: [
// 'blocks/interceptor/_auth-expired.interceptor.js'
// ]
// }
],
reactEntities: [
{
Expand Down Expand Up @@ -286,7 +272,6 @@ const files = {
// util
'shared/util/date-utils.ts',
'shared/util/pagination.constants.ts',
'shared/util/url-utils.ts',
'shared/util/entity-utils.ts',
// components
{ file: 'shared/auth/private-route.tsx', method: 'processJsx' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export class LoginService {
<%_ if (authenticationType === 'oauth2') { _%>
login() {
const port = (location.port ? ':' + location.port : '');
location.href = '//' + location.hostname + port + location.pathname + 'login';
location.href = '//' + location.hostname + port + location.pathname + 'authorize';
}
<%_ } else { _%>
login(credentials, callback?) {
Expand Down Expand Up @@ -72,7 +72,7 @@ export class LoginService {
}
<%_ } _%>
<%_ if (enableTranslation && authenticationType === 'uaa') { _%>

isAuthenticated() {
return this.accountService.isAuthenticated();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-%>
<%_ if (authenticationType === 'oauth2') { _%>
export const getLoginUrl = () => {
const port = location.port ? `:${location.port}` : '';
return `//${location.hostname}${port}/login`;
return `//${location.hostname}${port}${location.pathname}authorize`;
}
<%_ } _%>
51 changes: 26 additions & 25 deletions generators/common/templates/README.md.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -93,46 +93,47 @@ docker-compose -f src/main/docker/keycloak.yml up
The security settings in `src/main/resources/application.yml` are configured for this image.

```yaml
security:
basic:
enabled: false
spring:
...
security:
oauth2:
client:
accessTokenUri: http://localhost:9080/auth/realms/jhipster/protocol/openid-connect/token
userAuthorizationUri: http://localhost:9080/auth/realms/jhipster/protocol/openid-connect/auth
clientId: web_app
clientSecret: web_app
scope: openid profile email
resource:
userInfoUri: http://localhost:9080/auth/realms/jhipster/protocol/openid-connect/userinfo
client:
provider:
oidc:
issuer-uri: http://localhost:9080/auth/realms/jhipster
registration:
oidc:
client-id: web_app
client-secret: web_app
```

### 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`.
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.okta.com`.

Modify `src/main/resources/application.yml` to use your Okta settings.

```yaml
security:
basic:
enabled: false
spring:
...
security:
oauth2:
client:
accessTokenUri: https://{yourOktaDomain}.com/oauth2/default/v1/token
userAuthorizationUri: https://{yourOktaDomain}.com/oauth2/default/v1/authorize
clientId: {clientId}
clientSecret: {clientSecret}
scope: openid profile email
resource:
userInfoUri: https://{yourOktaDomain}.com/oauth2/default/v1/userinfo
client:
provider:
oidc:
issuer-uri: https://{yourOktaDomain}/oauth2/default
registration:
oidc:
client-id: {clientId}
client-secret: {clientSecret}
security:
```

Create an OIDC App in Okta to get a `{clientId}` and `{clientSecret}`. 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, 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 an OIDC App in Okta to get a `{clientId}` and `{clientSecret}`. 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, specify `http://localhost:8080` as a Base URI, and `http://localhost:8080/login/oauth2/code/oidc` as a Login Redirect URI. Click **Done**, then Edit and add `http://localhost:8080` as a Logout redirect URI. Copy and paste the client ID and secret into your `application.yml` file.

> **TIP:** If you want to use the [Ionic Module for JHipster](https://www.npmjs.com/package/generator-jhipster-ionic), you'll need to add `http://localhost:8100` as a **Login redirect URI** as well.

Create a `ROLE_ADMIN` and `ROLE_USER` group and add users into them. Create a user (e.g., "admin@jhipster.org" with password "Java is hip in 2017!"). Modify e2e tests to use this account when running integration tests. You'll need to change credentials in `src/test/javascript/e2e/account/account.spec.ts` and `src/test/javascript/e2e/admin/administration.spec.ts`.
Create a `ROLE_ADMIN` and `ROLE_USER` group and add users into them. Modify e2e tests to use this account when running integration tests. You'll need to change credentials in `src/test/javascript/e2e/account/account.spec.ts` and `src/test/javascript/e2e/admin/administration.spec.ts`.

Navigate to **API** > **Authorization Servers**, click the **Authorization Servers** tab and edit the default one. Click the **Claims** tab and **Add Claim**. Name it "roles", and include it in the ID Token. Set the value type to "Groups" and set the filter to be a Regex of `.*`.

Expand Down
100 changes: 33 additions & 67 deletions generators/server/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -441,16 +441,33 @@ const serverFiles = {
]
},
{
condition: generator => !shouldSkipUserManagement(generator) && generator.authenticationType === 'oauth2',
condition: generator =>
generator.authenticationType === 'oauth2' && ['monolith', 'gateway'].includes(generator.applicationType),
path: SERVER_MAIN_SRC_DIR,
templates: [
{
file: 'package/config/OAuth2Configuration.java',
renameTo: generator => `${generator.javaDir}config/OAuth2Configuration.java`
},
file: 'package/security/oauth2/AuthRedirectController.java',
renameTo: generator => `${generator.javaDir}security/oauth2/AuthRedirectController.java`
}
]
},
{
condition: generator => generator.authenticationType === 'oauth2',
path: SERVER_MAIN_SRC_DIR,
templates: [
{
file: 'package/security/OAuth2AuthenticationSuccessHandler.java',
renameTo: generator => `${generator.javaDir}security/OAuth2AuthenticationSuccessHandler.java`
file: 'package/security/oauth2/AudienceValidator.java',
renameTo: generator => `${generator.javaDir}security/oauth2/AudienceValidator.java`
}
]
},
{
condition: generator => generator.authenticationType === 'oauth2',
path: SERVER_TEST_SRC_DIR,
templates: [
{
file: 'package/security/oauth2/AudienceValidatorTest.java',
renameTo: generator => `${generator.javaDir}security/oauth2/AudienceValidatorTest.java`
}
]
},
Expand Down Expand Up @@ -581,21 +598,6 @@ const serverFiles = {
}
]
},
{
condition: generator =>
generator.applicationType === 'gateway' && generator.authenticationType === 'oauth2' && generator.serviceDiscoveryType,
path: SERVER_MAIN_SRC_DIR,
templates: [
{
file: 'package/config/OAuth2Configuration.java',
renameTo: generator => `${generator.javaDir}config/OAuth2Configuration.java`
},
{
file: 'package/security/OAuth2AuthenticationSuccessHandler.java',
renameTo: generator => `${generator.javaDir}security/OAuth2AuthenticationSuccessHandler.java`
}
]
},
{
condition: generator =>
generator.authenticationType === 'oauth2' &&
Expand Down Expand Up @@ -697,40 +699,12 @@ const serverFiles = {
]
},
{
condition: generator =>
!(
generator.applicationType !== 'microservice' &&
!(
generator.applicationType === 'gateway' &&
(generator.authenticationType === 'uaa' || generator.authenticationType === 'oauth2')
)
) && generator.authenticationType === 'oauth2',
path: SERVER_MAIN_SRC_DIR,
templates: [
{
file: 'package/security/oauth2/AuthorizationHeaderUtil.java',
renameTo: generator => `${generator.javaDir}security/oauth2/AuthorizationHeaderUtil.java`
},
{
file: 'package/security/oauth2/SimplePrincipalExtractor.java',
renameTo: generator => `${generator.javaDir}security/oauth2/SimplePrincipalExtractor.java`
},
{
file: 'package/security/oauth2/SimpleAuthoritiesExtractor.java',
renameTo: generator => `${generator.javaDir}security/oauth2/SimpleAuthoritiesExtractor.java`
}
]
},
{
condition: generator =>
generator.applicationType === 'microservice' &&
generator.authenticationType === 'oauth2' &&
generator.cacheProvider !== 'no',
condition: generator => generator.authenticationType === 'oauth2' && generator.applicationType === 'gateway',
path: SERVER_MAIN_SRC_DIR,
templates: [
{
file: 'package/security/oauth2/CachedUserInfoTokenServices.java',
renameTo: generator => `${generator.javaDir}security/oauth2/CachedUserInfoTokenServices.java`
file: 'package/security/oauth2/AuthorizationHeaderFilter.java',
renameTo: generator => `${generator.javaDir}security/oauth2/AuthorizationHeaderFilter.java`
}
]
},
Expand All @@ -740,6 +714,10 @@ const serverFiles = {
(generator.applicationType === 'microservice' || generator.applicationType === 'gateway'),
path: SERVER_MAIN_SRC_DIR,
templates: [
{
file: 'package/security/oauth2/AuthorizationHeaderUtil.java',
renameTo: generator => `${generator.javaDir}security/oauth2/AuthorizationHeaderUtil.java`
},
{
file: 'package/config/FeignConfiguration.java',
renameTo: generator => `${generator.javaDir}config/FeignConfiguration.java`
Expand All @@ -752,31 +730,19 @@ const serverFiles = {
file: 'package/client/OAuth2InterceptedFeignConfiguration.java',
renameTo: generator => `${generator.javaDir}client/OAuth2InterceptedFeignConfiguration.java`
},
{
file: 'package/config/OAuth2TokenServicesConfiguration.java',
renameTo: generator => `${generator.javaDir}config/OAuth2TokenServicesConfiguration.java`
},
{
file: 'package/client/TokenRelayRequestInterceptor.java',
renameTo: generator => `${generator.javaDir}client/TokenRelayRequestInterceptor.java`
}
]
},
{
condition: generator =>
!(
generator.applicationType !== 'microservice' &&
!(
generator.applicationType === 'gateway' &&
(generator.authenticationType === 'uaa' || generator.authenticationType === 'oauth2')
)
) &&
(generator.authenticationType === 'oauth2' && generator.applicationType === 'gateway'),
condition: generator => generator.authenticationType === 'oauth2',
path: SERVER_MAIN_SRC_DIR,
templates: [
{
file: 'package/config/OAuth2SsoConfiguration.java',
renameTo: generator => `${generator.javaDir}config/OAuth2SsoConfiguration.java`
file: 'package/config/SecurityConfiguration.java',
renameTo: generator => `${generator.javaDir}config/SecurityConfiguration.java`
}
]
},
Expand Down
15 changes: 6 additions & 9 deletions generators/server/templates/build.gradle.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -343,9 +343,8 @@ dependencies {
implementation ("com.github.vanroy:spring-boot-starter-data-jest") {
exclude module: "commons-logging"
}
// log4j needed to create embedded elasticsearch instance
runtimeOnly "org.apache.logging.log4j:log4j-api:2.7"
runtimeOnly "org.apache.logging.log4j:log4j-core:2.7"
// log4j2-mock needed to create embedded elasticsearch instance with SLF4J
runtimeOnly "de.dentrassi.elasticsearch:log4j2-mock:0.0.1"
// end of Spring Data Jest dependencies
<%_ } _%>
<%_ if (['mongodb', 'cassandra', 'couchbase'].includes(databaseType)) { _%>
Expand Down Expand Up @@ -395,7 +394,7 @@ dependencies {
implementation "org.springframework.cloud:spring-cloud-starter-consul-discovery"
implementation "org.springframework.cloud:spring-cloud-starter-consul-config"
<%_ } _%>
<%_ if (authenticationType === 'oauth2' || authenticationType === 'uaa') { _%>
<%_ if (authenticationType === 'uaa') { _%>
implementation "org.springframework.cloud:spring-cloud-security"
<%_ } _%>
<%_ if (applicationType === 'microservice' || applicationType === 'gateway' || applicationType === 'uaa') { _%>
Expand All @@ -409,11 +408,8 @@ dependencies {
implementation "org.springframework.security:spring-security-messaging"
<%_ } _%>
<%_ if (authenticationType === 'oauth2') { _%>
implementation "org.springframework.security.oauth:spring-security-oauth2"
implementation "org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure"
<%_ if (applicationType === 'gateway' || applicationType === 'microservice') { _%>
implementation "org.springframework.security:spring-security-jwt"
<%_ } _%>
implementation "org.springframework.boot:spring-boot-starter-oauth2-client"
implementation "org.springframework.boot:spring-boot-starter-oauth2-resource-server"
<%_ } _%>
<%_ if (authenticationType === 'jwt') { _%>
implementation "io.jsonwebtoken:jjwt-api"
Expand All @@ -422,6 +418,7 @@ dependencies {
<%_ } _%>
<%_ if (authenticationType === 'uaa') { _%>
implementation "org.springframework.security.oauth:spring-security-oauth2"
implementation "org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure"
implementation "org.springframework.security:spring-security-jwt"
<%_ } _%>
<%_ if (databaseType === 'mongodb') { _%>
Expand Down
Loading