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

Spring Security 5 OAuth2 #1339

Merged
merged 41 commits into from
Aug 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
f72c4bc
Initial working version of OAuth using in memory stores.
ericenns Jul 6, 2022
2d8d1fb
Update how current user is accessed in services and repositories.
ericenns Jul 7, 2022
2ebef56
Add back CURRENT_USER_DETAILS to session.
ericenns Jul 8, 2022
3bd8ffe
Working OAuth authentication using db backend.
ericenns Jul 8, 2022
18e5cbf
OAuth2 working again with IridaClientDetails
ericenns Jul 8, 2022
fa964e5
Added in liquibase migration for adding in OAuth2 authorization tables.
ericenns Jul 12, 2022
b0d1052
Remvoved old OAuth code and fixed some tests.
ericenns Jul 12, 2022
aa508e9
Fix OAuth2 password grant scope parameter validation.
ericenns Jul 12, 2022
3263cf0
Update OAuth2 flow for remote IRIDA connections to use state variable…
ericenns Jul 13, 2022
f54a286
Change remote_api_token token storage to use TEXT instead of BLOB.
ericenns Jul 13, 2022
03a6764
Fix javadoc issues.
ericenns Jul 13, 2022
4c1da4e
Fix javadoc
ericenns Jul 13, 2022
3b4b6cc
Added in token revocation
ericenns Jul 13, 2022
5e9f927
Update JWT to use provided RSA public and private keys specified in c…
ericenns Jul 14, 2022
04a87ed
Attempt fix galaxy integration tests.
ericenns Jul 14, 2022
3faba73
Merge branch 'development' into spring-security-5-oauth2
ericenns Jul 14, 2022
2c476bc
Attempt fix galaxy integration tests take two.
ericenns Jul 14, 2022
6676ee0
Add back in missing auto config for galaxy integration tests.
ericenns Jul 14, 2022
5f6552f
Add Transactional annotations to all methods in IridaOAuth2Authorizat…
ericenns Jul 15, 2022
579846f
Moved stateMap for remote api OAuth flow into session object, instead…
ericenns Jul 20, 2022
1fbc42d
Updated SecurityIT to check for expected authentication scheme in res…
ericenns Jul 20, 2022
8076794
Added in documentation for generation the JWK.
ericenns Jul 22, 2022
c797985
Remove old oauth token tables.
ericenns Jul 25, 2022
f64f178
Add in RSA key bit size specification to RSA generation gradle task.
ericenns Jul 25, 2022
2c7221b
Added in missing javadoc and updated comments.
ericenns Jul 28, 2022
60ace7d
Add in missing translations to OAuth2 authorization consent page.
ericenns Jul 28, 2022
d503cde
Reverted OAuth2 authorization consent to be the same as it was before…
ericenns Aug 3, 2022
403df7b
Fix remote api tests after removing scope checkboxes.
ericenns Aug 3, 2022
3a104fe
Remove auto approval scopes for OAuth2 clients.
ericenns Aug 3, 2022
64444b1
Update screenshot for editing client details.
ericenns Aug 3, 2022
a3f26c4
Update client-details screenshot for tutorial in docs.
ericenns Aug 3, 2022
091a6f7
Remove old client_details tables that are no longer required.
ericenns Aug 4, 2022
0d5fd60
Merge branch 'development' into spring-security-5-oauth2
ericenns Aug 5, 2022
1ebd1ac
Merge branch 'development' into spring-security-5-oauth2
ericenns Aug 5, 2022
bc31bfd
Changed from RSA only support for JWK to use a Java Key Store.
ericenns Aug 9, 2022
564373e
Merge remote-tracking branch 'origin/development' into spring-securit…
ericenns Aug 11, 2022
468a078
Update exclude in gradle build to ignore java key store.
ericenns Aug 11, 2022
40becd4
Add comment to Order of SecurityFilterChains in IridaOauthSecurityConfig
ericenns Aug 11, 2022
734b202
Added in changelog entry for OAuth2 upgrade.
ericenns Aug 11, 2022
a7b2d28
Update to latest version of spring-security-oauth2-authorization-server
ericenns Aug 11, 2022
0255b9c
Fix path in java keystore generation example.
ericenns Aug 16, 2022
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ gradle-app.setting
.gradletasknamecache
!**/src/main/**/build/
!**/src/test/**/build/
*.jks

### STS ###
.apt_generated
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* [REST]: Updated synchronizing of sample data to remove sequencing objects and assemblies that no longer exist on the remote sample. See [PR 1345](https://github.com/phac-nml/irida/pull/1345)
* [UI]: Fixed issue with filtering samples by files using a windows encoded text file causing sample name truncation. See [PR 1346](https://github.com/phac-nml/irida/pull/1346)
* [Developer]: Fixed deleting a project with project subscriptions. See [PR 1348](https://github.com/phac-nml/irida/pull/1348)
* [Developer]: Updated OAuth2 implemention to use Spring Security 5 OAuth2 libraries. See [PR 1339](https://github.com/phac-nml/irida/pull/1339)

## [22.05.5] - 2022/06/28
* [UI]: Fixed bug preventing export of project samples table due to invalid url. [PR 1331](https://github.com/phac-nml/irida/pull/1331)
Expand Down
13 changes: 10 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ dependencies {
}
implementation("org.springframework.boot:spring-boot-starter-validation")
implementation("org.springframework.boot:spring-boot-starter-security")
implementation("org.springframework.security:spring-security-oauth2-authorization-server:0.3.1")
implementation("org.springframework.security:spring-security-oauth2-resource-server:5.7.2")
implementation("org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:1.0.0") {
exclude(group = "org.slf4j")
}
Expand All @@ -146,9 +148,6 @@ dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-web-services")
implementation("org.springframework.boot:spring-boot-starter-hateoas")
implementation("org.springframework.security.oauth:spring-security-oauth2:2.3.6.RELEASE") {
exclude(group = "org.codehaus.jackson", module = "jackson-mapper-asl")
}
implementation("commons-io:commons-io:2.11.0")
implementation("commons-fileupload:commons-fileupload:1.4")
implementation("org.apache.poi:poi-ooxml:5.2.2") {
Expand Down Expand Up @@ -266,6 +265,7 @@ tasks.war {
exclude("entries.js")
exclude(".eslintrc.js")
exclude("postcss.config.js")
rootSpec.exclude("**/jwk-key-store.jks")
}

node {
Expand Down Expand Up @@ -423,6 +423,12 @@ tasks.named<BootRun>("bootRun") {
}
}

task<Exec>("generateJWKKeyStore") {
workingDir(file("${projectDir}/src/main/resources"))
commandLine(listOf("keytool", "-genkeypair", "-alias", "JWK", "-keyalg", "RSA", "-noprompt", "-dname", "CN=irida.bioinformatics.corefacility.ca, OU=ID, O=IRIDA, L=IRIDA, S=IRIDA, C=CA", "-keystore", "jwk-key-store.jks", "-validity", "3650", "-storepass", "SECRET", "-keypass", "SECRET", "-storetype", "PKCS12"))
outputs.file(file("${projectDir}/src/main/resources/jwk-key-store.jks"))
}

openApi {
outputDir.set(file("${projectDir}/doc/swagger-ui"))
outputFileName.set("open-api.json")
Expand All @@ -434,6 +440,7 @@ tasks.processResources {
expand(project.properties)
}
dependsOn(":buildWebapp")
dependsOn(":generateJWKKeyStore")
}

tasks.javadoc {
Expand Down
4 changes: 4 additions & 0 deletions doc/administrator/web/config/irida.conf
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ file.processing.max.size=8
file.processing.queue.capacity=512
file.processing.process=true

##### OAuth2 JWT security settings.
# Default keystore for holding public/private keys required for OAuth2 JWK Access Token encryption/decryption
oauth2.jwk.key-store=/etc/irida/jwk-key-store.jks
oauth2.jwk.key-store-password=SECRET

##### The database-specific settings. Several examples of how to specify a
##### Hibernate driver are listed below (but commented out).
Expand Down
11 changes: 11 additions & 0 deletions doc/administrator/web/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,17 @@ The main configuration parameters you will need to change are:
* `ncbi.upload.namespace` - Prefix for file upload identifiers to NCBI. The namespace is used to guarantee upload IDs are unique. This configuration option is used as a placeholder and may still be set by the user.
5. **Security configuration**
* `security.password.expiry` - The number of days a password is valid for in IRIDA. After a password expires the user will be required to create a new one. Passwords cannot be reused.
6. **OAuth2 JWK security configuration** - IRIDA uses JWT (Json Web Tokens) for OAuth2 and as such requires a Java Key Store with an entry stored in PKCS12 format. The key pair entry can be in either RSA or EC (curves allowed are P-256, P-384, and P-121) format. The password for the keystore must be the same as the password for the key entry (This is default for PKCS12 format). (Note: these keys have nothing to do with SSL).
* `oauth2.jwk.key-store=/etc/irida/jwk-key-store.jks` - The location of the Java Key Store
* `oauth2.jwk.key-store-password=SECRET` - The Java Key Store password

### OAuth2 JWK Java Key Store generation
The Java Key Store required to encrypt and decrypt the JWT's can be generated with the following commands:
```bash
keytool -genkeypair -alias JWK -keyalg RSA -noprompt -dname "CN=irida.bioinformatics.corefacility.ca, OU=ID, O=IRIDA, L=IRIDA, S=IRIDA, C=CA" -keystore /etc/irida/jwk-key-store.jks -validity 3650 -storepass SECRET -keypass SECRET -storetype PKCS12
```

This will generate a Java Key Store with an entry aliased `JWK` with an expiry of 10 years and a password of `SECRET`.

Web Configuration
-----------------
Expand Down
Binary file modified doc/images/tutorials/clients/client-details.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified doc/user/administrator/images/edit-client-details.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package ca.corefacility.bioinformatics.irida.config.repository;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.hibernate.envers.AuditReader;
import org.hibernate.envers.AuditReaderFactory;
Expand All @@ -13,8 +12,6 @@
import org.springframework.data.envers.repository.support.EnversRevisionRepositoryFactoryBean;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import ca.corefacility.bioinformatics.irida.config.data.IridaApiJdbcDataSourceConfig;
Expand All @@ -23,14 +20,15 @@

/**
* Configuration for repository/data storage classes.
*
*
*/
@Configuration
@EnableTransactionManagement(order = IridaApiRepositoriesConfig.TRANSACTION_MANAGEMENT_ORDER)
@EnableJpaRepositories(basePackages = "ca.corefacility.bioinformatics.irida.repositories", repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean.class)
@EnableJpaRepositories(basePackages = "ca.corefacility.bioinformatics.irida.repositories",
repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean.class)
@ComponentScan("ca.corefacility.bioinformatics.irida.repositories.remote")
@Import({ IridaApiPropertyPlaceholderConfig.class, IridaApiJdbcDataSourceConfig.class,
@Import({
IridaApiPropertyPlaceholderConfig.class,
IridaApiJdbcDataSourceConfig.class,
IridaApiFilesystemRepositoryConfig.class })
@EnableJpaAuditing
public class IridaApiRepositoriesConfig {
Expand All @@ -49,10 +47,4 @@ public RevisionListener revisionListener() {
public AuditReader auditReader(EntityManagerFactory entityManagerFactory) {
return AuditReaderFactory.get(entityManagerFactory.createEntityManager());
}

@Bean(name="iridaTokenStore")
public TokenStore tokenStore(DataSource dataSource) {
TokenStore store = new JdbcTokenStore(dataSource);
return store;
}
}
Loading