Skip to content

Commit

Permalink
Merge pull request #7 from OSGP/feature/optional-access-token
Browse files Browse the repository at this point in the history
FDP-893: Make access token optional
  • Loading branch information
jasperkamerling authored Oct 18, 2023
2 parents 13171f4 + 4e945f0 commit ac4c8e9
Show file tree
Hide file tree
Showing 19 changed files with 208 additions and 51 deletions.
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
17 changes: 17 additions & 0 deletions oauth-token-client/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,20 @@ publishing {
}
}
}

testing {
suites {
register<JvmTestSuite>("integrationTest") {
useJUnitJupiter()
dependencies {
implementation(project())
implementation("org.springframework.boot:spring-boot-starter-test")
implementation("org.mock-server:mockserver-spring-test-listener:5.15.0")
}
}
}
}

tasks.check {
dependsOn("integrationTest")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.gxf.utilities.spring.oauth

import com.gxf.utilities.spring.oauth.providers.NoTokenProvider
import com.gxf.utilities.spring.oauth.providers.TokenProvider
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.test.context.TestPropertySource
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig


@SpringJUnitConfig(OAuthTokenClientContext::class)
@TestPropertySource("classpath:oauth-disabled.properties")
class NoTokenProviderTest {

@Autowired
lateinit var tokenProvider: TokenProvider

@Test
fun test() {
assert(tokenProvider is NoTokenProvider)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.gxf.utilities.spring.oauth

import com.gxf.utilities.spring.oauth.providers.OAuthTokenProvider
import com.gxf.utilities.spring.oauth.providers.TokenProvider
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.test.context.TestPropertySource
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig


@SpringJUnitConfig(OAuthTokenClientContext::class)
@TestPropertySource("classpath:oauth-enabled.properties")
class OAuthTokenProviderTest {

@Autowired
lateinit var tokenProvider: TokenProvider

@Test
fun test() {
assert(tokenProvider is OAuthTokenProvider)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
-----BEGIN CERTIFICATE-----
MIIDczCCAlsCFFZ9i8q7ww4tBsuq1NslyXCB4Mj9MA0GCSqGSIb3DQEBCwUAMHYx
CzAJBgNVBAYTAk5MMRMwEQYDVQQIDApHZWxkZXJsYW5kMQ8wDQYDVQQHDAZBcm5o
ZW0xFTATBgNVBAoMDEFsbGlhbmRlciBOVjEQMA4GA1UECwwHSW9UIEZEUDEYMBYG
A1UEAwwPZ3hmLWxzbWV0ZW4tdHN0MB4XDTIyMDcwNTA5MjUwOFoXDTIzMDcwNTA5
MjUwOFowdjELMAkGA1UEBhMCTkwxEzARBgNVBAgMCkdlbGRlcmxhbmQxDzANBgNV
BAcMBkFybmhlbTEVMBMGA1UECgwMQWxsaWFuZGVyIE5WMRAwDgYDVQQLDAdJb1Qg
RkRQMRgwFgYDVQQDDA9neGYtbHNtZXRlbi10c3QwggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQDOS7Tr+imTy0IB+8gdq0z1bI2N3hJtY+uLvymqyyjfWv8i
ATAu0OZgaYcXj/vcls01lMSLE2nF+z+yFivD0ErZ7dQc9v9+NSMon8M8BaP9o+o6
50xeHGlUFEcelhpfMUH9yVaWhh1BE6Mt3ZfxzFZNq30E/9Vnal9dniUoBtGxzf7x
HnNxT1l1AS1Kbj4ft/+iDkZHIoAOvkndvLlgQaF1JryWuZYU83F1xT8HztmRXSrT
+dNpCiYJZPh9/CWpqrC/lGlK28m1x7EJN60vw8f54dfsT+En1TcP/u9hz7cPRRIa
FpHI5PScfTrmRsWWbNOETh5pcB1JWvV9q2iV3LPtAgMBAAEwDQYJKoZIhvcNAQEL
BQADggEBAJqZjQlHMYh0VYwxlXshBAZh79vKX/dBalUd7yvse2Q5g2FaXnXlmybT
B5c20N4QAOgDWFhcSyD5kBFKif245l56KGZ1wLn3ZUn9wWNLHDXWLZMRPgwGkKz4
WQrYv19mSobGbvMa5wypw5KgcBeXpcQmzD43EtmBQzFwRSQ+uQTmVAmfYgktsUPb
xODett5N2XYQLEv31tMc9J5FUOwMeer6VrLPVcQvFrbCJ5x0O3n7dhH1eyQ3OGIJ
N9E27gCkEK59IPHCW9yvmcWqr58BqckDiHjBuZdQAZ/Zq1B/PFc4Fuf2PcFETRxl
1g2FHvm9qmM/ol961jhGYq0Bt2Seimo=
-----END CERTIFICATE-----
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDOS7Tr+imTy0IB
+8gdq0z1bI2N3hJtY+uLvymqyyjfWv8iATAu0OZgaYcXj/vcls01lMSLE2nF+z+y
FivD0ErZ7dQc9v9+NSMon8M8BaP9o+o650xeHGlUFEcelhpfMUH9yVaWhh1BE6Mt
3ZfxzFZNq30E/9Vnal9dniUoBtGxzf7xHnNxT1l1AS1Kbj4ft/+iDkZHIoAOvknd
vLlgQaF1JryWuZYU83F1xT8HztmRXSrT+dNpCiYJZPh9/CWpqrC/lGlK28m1x7EJ
N60vw8f54dfsT+En1TcP/u9hz7cPRRIaFpHI5PScfTrmRsWWbNOETh5pcB1JWvV9
q2iV3LPtAgMBAAECggEAOjFi9NoZlmZU1Whn9+6Vg/m+KJHHUvJHxKEFKPesLO1n
YPlC1UH6aqH6CKyGGKC1fHLdynmMcdvBCQR2DgOYycbr+cu3IKvuogwHL8xLiUYO
0dTjVvzevWgG89rVz5p+ig+cjFOCtxPKCSskLII+qiRA3QMp+MUp56evxY2+40+9
+Av1BPwbtyneETudFI1ZsmOL8eJIrlhDO83ZUrfQWX3vExrjChrQ7RXTYG+KZTvk
/XOE7FjVj6bfl8p+0c7LVHqckEunmbW6YxkxRkGfxm1SxHirJDEPmXN4Dp+b1yFs
3hVS+FR3+iw8Fr4J489RGf4fLr/eLJM8ZBOCGr7ApQKBgQDqeTs/vLS6/cNCF814
MZsf+/6C6/EF11XaQSGh1RpbSSuBPeISLuBDK3Gq9D0T+1uvnf1MD2mpdiqytif5
Yztt1BsB2YxjSRGnhzWyQcwSNK2RsDAv1I8wBMDD1AqMRF6lOxajtoTww9jcac2w
AdEmLrGOb2YdYqt8KpRl2FWQhwKBgQDhPDgn6H0yc3QSyVz8J6hGDhhQ+Cb8qmms
m/7SBVs3JJjBANPGPheR8FWmL3kx2XB+gHcoWAKVhY3W2jQLiQhtbZY4Y85F4Lix
zLwrYEDE9dz6AcARFUn9pe7fNfsxppaNcodxCHRBg7K5s1JJ22+BK5TDiHJeqvD8
u9IIkRC46wKBgQCWZokgyzTKtTfoT0hXDsrIa2XIKPwDmSrSwvCF1CIB6B9l2YIH
09W6gEV7OQtso9EeByORBFnsf4XH+JwPlh1qx6FDQH6SuS3/3fUNkLMMAopLZ06h
f6ERVhsoAf16F+j1578P6GXB4n5ac+uiOKgl69Gs4bwIoWAKV221Hl1URQKBgFEv
yrIf7FjuIs3OxXSiutYdqIgvGqaCqrqsNCryAVIcH++Z47wWj5psPgM8I3xje1gt
6EWji7LnxBvI5W+vAlmnYbmLyEOJ4Ck+uikMdexJD1ESpm/B87y5PiQ5KgVYnfX4
bXfB613eIeMsDyJONaAi3Gmq2kbjaSBAd1HdMGDnAoGAbwOHbvixgJSQOiLO8Tb6
DW8nkpHGexvMO4gLKHTnHLduTXfi3P/3RsoR/uNOp8yeZqZtjE4XZkGLXAfCQ7uz
qgODUqk36Fwu3SVoN/hXGJrOAWRobxfO8EQLp3JRr492yZnIPO/r3ydq18m/IEpe
/KJ/h0ZjDm4gWtcxDuFBMEA=
-----END PRIVATE KEY-----
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
### OAUTH ###
oauth.client.enabled=false
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ package com.gxf.utilities.spring.oauth

import com.gxf.utilities.spring.oauth.config.OAuthClientConfig
import com.gxf.utilities.spring.oauth.config.OAuthClientProperties
import com.gxf.utilities.spring.oauth.services.OAuthTokenProvider
import com.gxf.utilities.spring.oauth.providers.NoTokenProvider
import com.gxf.utilities.spring.oauth.providers.OAuthTokenProvider
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Import

@Configuration
@Import(OAuthClientConfig::class, OAuthTokenProvider::class, OAuthClientProperties::class)
@Import(OAuthClientConfig::class, OAuthClientProperties::class, OAuthTokenProvider::class, NoTokenProvider::class)
class OAuthTokenClientContext
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ SPDX-License-Identifier: Apache-2.0
*/
package com.gxf.utilities.spring.oauth.config

import com.gxf.utilities.spring.oauth.config.condition.OAuthEnabledCondition
import com.gxf.utilities.spring.oauth.exceptions.OAuthTokenException
import com.microsoft.aad.msal4j.ClientCredentialFactory
import com.microsoft.aad.msal4j.ClientCredentialParameters
Expand All @@ -26,7 +27,7 @@ import java.util.*
import java.util.stream.Collectors

@Configuration
@Conditional(OauthClientCondition::class)
@Conditional(OAuthEnabledCondition::class)
class OAuthClientConfig {

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ SPDX-License-Identifier: Apache-2.0
*/
package com.gxf.utilities.spring.oauth.config

import com.gxf.utilities.spring.oauth.config.condition.OAuthEnabledCondition
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Conditional
import org.springframework.context.annotation.Configuration
import org.springframework.core.io.Resource

@Configuration
@Conditional(OauthClientCondition::class)
@Conditional(OAuthEnabledCondition::class)
class OAuthClientProperties(
@Value("\${oauth.client.client-id}")
val clientId: String,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
SPDX-FileCopyrightText: Contributors to the GXF project
SPDX-License-Identifier: Apache-2.0
*/
package com.gxf.utilities.spring.oauth.config.condition

import org.springframework.context.annotation.Condition
import org.springframework.context.annotation.ConditionContext

/**
* Condition to enable or disable the Oauth Client components
*/
abstract class OAuthCondition : Condition {
fun oAuthEnabled(context: ConditionContext) =
context.environment.getProperty("oauth.client.enabled").equals("true", ignoreCase = true)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
SPDX-FileCopyrightText: Contributors to the GXF project
SPDX-License-Identifier: Apache-2.0
*/
package com.gxf.utilities.spring.oauth.config.condition

import org.springframework.context.annotation.ConditionContext
import org.springframework.core.type.AnnotatedTypeMetadata

/**
* Condition if OAuth is disabled
*/
class OAuthDisabledCondition : OAuthCondition() {
override fun matches(context: ConditionContext, metadata: AnnotatedTypeMetadata): Boolean =
!oAuthEnabled(context)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
SPDX-FileCopyrightText: Contributors to the GXF project
SPDX-License-Identifier: Apache-2.0
*/
package com.gxf.utilities.spring.oauth.config.condition

import org.springframework.context.annotation.ConditionContext
import org.springframework.core.type.AnnotatedTypeMetadata

/**
* Condition if OAuth is enabled
*/
class OAuthEnabledCondition : OAuthCondition() {
override fun matches(context: ConditionContext, metadata: AnnotatedTypeMetadata): Boolean =
oAuthEnabled(context)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.gxf.utilities.spring.oauth.providers

import com.gxf.utilities.spring.oauth.config.condition.OAuthDisabledCondition
import org.springframework.context.annotation.Conditional
import org.springframework.stereotype.Service
import java.util.*

@Service
@Conditional(OAuthDisabledCondition::class)
class NoTokenProvider : TokenProvider {
/**
* Returns an empty optional indicating that no oauth provider is configured.
*/
override fun getAccessToken(): Optional<String> =
Optional.empty<String>()
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,31 @@ SPDX-FileCopyrightText: Contributors to the GXF project
SPDX-License-Identifier: Apache-2.0
*/
package com.gxf.utilities.spring.oauth.services
package com.gxf.utilities.spring.oauth.providers

import com.gxf.utilities.spring.oauth.config.OauthClientCondition
import com.gxf.utilities.spring.oauth.config.condition.OAuthEnabledCondition
import com.microsoft.aad.msal4j.ClientCredentialParameters
import com.microsoft.aad.msal4j.ConfidentialClientApplication
import com.microsoft.aad.msal4j.IAuthenticationResult
import org.springframework.context.annotation.Conditional
import org.springframework.context.annotation.Primary
import org.springframework.stereotype.Service
import java.util.Optional

@Service
@Conditional(OauthClientCondition::class)
@Primary
@Conditional(OAuthEnabledCondition::class)
class OAuthTokenProvider(
private val confidentialClientApplication: ConfidentialClientApplication,
private val parameters: ClientCredentialParameters
) {
private val parameters: ClientCredentialParameters,
) : TokenProvider {

/**
* Retrieve an oauth token from the oauth provider.
* Tokens are cached by the msal4j Library so no caching needed here.
*/
fun getAccessToken(): String =
getOAuthToken().accessToken()
override fun getAccessToken(): Optional<String> =
Optional.of(getOAuthToken().accessToken())

/**
* Retrieve an oauth object from the oauth provider.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.gxf.utilities.spring.oauth.providers

import java.util.*

interface TokenProvider {
/**
* Retrieve an access token for instance from an oauth provider.
* Tokens are cached internally, there is no need to cache them outside of this library.
*/
fun getAccessToken(): Optional<String>
}

This file was deleted.

0 comments on commit ac4c8e9

Please sign in to comment.