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 23 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/
*.pem

### STS ###
.apt_generated
Expand Down
33 changes: 30 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.0")
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-*.pem")
apetkau marked this conversation as resolved.
Show resolved Hide resolved
}

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

task<Exec>("generateRSAKeyPair") {
workingDir(file("${projectDir}/src/main/resources"))
commandLine(listOf("openssl", "genpkey", "-algorithm", "RSA", "-out", "jwk-keypair.pem"))
outputs.file(file("${projectDir}/src/main/resources/jwk-keypair.pem"))
}

task<Exec>("generateRSAPrivateKey") {
dependsOn(":generateRSAKeyPair")
workingDir(file("${projectDir}/src/main/resources"))
commandLine(listOf("openssl", "pkcs8", "-inform", "PEM", "-outform", "PEM", "-nocrypt", "-in", "jwk-keypair.pem", "-out", "jwk-private.pem"))
outputs.file(file("${projectDir}/src/main/resources/jwk-private.pem"))
}

task<Exec>("generateRSAPublicKey") {
dependsOn(":generateRSAKeyPair")
workingDir(file("${projectDir}/src/main/resources"))
commandLine(listOf("openssl", "rsa", "-in", "jwk-keypair.pem", "-pubout", "-out", "jwk-public.pem"))
outputs.file(file("${projectDir}/src/main/resources/jwk-public.pem"))
}

task<DefaultTask>("generateJWK") {
dependsOn("generateRSAKeyPair")
dependsOn("generateRSAPrivateKey")
dependsOn("generateRSAPublicKey")
}

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

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.
oauth2.jwk.rsakey.id=CHANGEME
oauth2.jwk.rsakey.private=/etc/irida/jwk-private.pem
oauth2.jwk.rsakey.public=/etc/irida/jwk-public.pem

##### The database-specific settings. Several examples of how to specify a
##### Hibernate driver are listed below (but commented out).
Expand Down
15 changes: 15 additions & 0 deletions doc/administrator/web/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,21 @@ 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 JWK (Json Web Key) in RSA format to encrypt and decrypt these tokens.
apetkau marked this conversation as resolved.
Show resolved Hide resolved
* `oauth2.jwk.rsakey.id=CHANGEME` - The id for the RSA private and public keys (used to select the correct keys for encryption and decryption)
apetkau marked this conversation as resolved.
Show resolved Hide resolved
* `oauth2.jwk.rsakey.private=/etc/irida/jwk-private.pem` - The RSA private key
* `oauth2.jwk.rsakey.public=classpath:/jwk-public.pem` - The RSA public key
apetkau marked this conversation as resolved.
Show resolved Hide resolved

### OAuth2 JWK RSA Key generation
The RSA keys used to encrypt and decrypt the JWT's can be generated with the following commands:
apetkau marked this conversation as resolved.
Show resolved Hide resolved
```bash
# First generate the RSA Keypair
openssl genpkey -algorithm RSA -out /etc/irida/jwk-keypair.pem
# Second extract the RSA private key from the RSA Keypair
openssl pkcs8 -inform PEM -outform PEM -nocrypt -in /etc/irida/jwk-keypair.pem -out /etc/irida/jwk-private.pem
# Third extract the RSA public key from the RSA Keypair
openssl rsa -in /etc/irida/jwk-keypair.pem -pubout -out /etc/irida/jwk-public.pem
```

Web Configuration
-----------------
Expand Down
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