-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feature - add interactive login page (#1)
* serve login html when login prompt is specified * formatting, refactoring, and fix failing test for interactive login * set interactivelogin=true as default for standalone server * show debug info on login page * enqueue MockResponse and use this if added instead of OAuth2HttpRequestHandler
- Loading branch information
1 parent
df4afcf
commit fb191cc
Showing
27 changed files
with
1,013 additions
and
420 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
44 changes: 0 additions & 44 deletions
44
src/main/kotlin/no/nav/security/mock/extensions/MockResponseExtensions.kt
This file was deleted.
Oops, something went wrong.
29 changes: 0 additions & 29 deletions
29
src/main/kotlin/no/nav/security/mock/extensions/RecordedRequestExtensions.kt
This file was deleted.
Oops, something went wrong.
106 changes: 106 additions & 0 deletions
106
src/main/kotlin/no/nav/security/mock/oauth2/MockOAuth2Server.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
package no.nav.security.mock.oauth2 | ||
|
||
import com.nimbusds.jwt.SignedJWT | ||
import com.nimbusds.oauth2.sdk.AuthorizationCode | ||
import com.nimbusds.oauth2.sdk.AuthorizationCodeGrant | ||
import com.nimbusds.oauth2.sdk.TokenRequest | ||
import com.nimbusds.oauth2.sdk.auth.ClientSecretBasic | ||
import com.nimbusds.oauth2.sdk.auth.Secret | ||
import com.nimbusds.oauth2.sdk.id.ClientID | ||
import mu.KotlinLogging | ||
import no.nav.security.mock.oauth2.extensions.asOAuth2HttpRequest | ||
import no.nav.security.mock.oauth2.extensions.toAuthorizationEndpointUrl | ||
import no.nav.security.mock.oauth2.extensions.toJwksUrl | ||
import no.nav.security.mock.oauth2.extensions.toTokenEndpointUrl | ||
import no.nav.security.mock.oauth2.extensions.toWellKnownUrl | ||
import no.nav.security.mock.oauth2.http.OAuth2HttpRequestHandler | ||
import no.nav.security.mock.oauth2.http.OAuth2HttpResponse | ||
import no.nav.security.mock.oauth2.token.OAuth2TokenCallback | ||
import no.nav.security.mock.oauth2.token.OAuth2TokenProvider | ||
import okhttp3.HttpUrl | ||
import okhttp3.mockwebserver.Dispatcher | ||
import okhttp3.mockwebserver.MockResponse | ||
import okhttp3.mockwebserver.MockWebServer | ||
import okhttp3.mockwebserver.RecordedRequest | ||
import java.io.IOException | ||
import java.net.InetSocketAddress | ||
import java.net.URI | ||
import java.util.concurrent.BlockingQueue | ||
import java.util.concurrent.LinkedBlockingQueue | ||
|
||
private val log = KotlinLogging.logger {} | ||
|
||
class MockOAuth2Server( | ||
config: OAuth2Config = OAuth2Config() | ||
) { | ||
private val mockWebServer: MockWebServer = MockWebServer() | ||
private val tokenProvider: OAuth2TokenProvider = | ||
OAuth2TokenProvider() | ||
|
||
var dispatcher: Dispatcher = MockOAuth2Dispatcher(config) | ||
|
||
fun start() { | ||
mockWebServer.start() | ||
mockWebServer.dispatcher = dispatcher | ||
} | ||
|
||
fun start(port: Int = 0) { | ||
val address = InetSocketAddress(0).address | ||
log.info("attempting to start server on port $port and InetAddress=$address") | ||
mockWebServer.start(address, port) | ||
mockWebServer.dispatcher = dispatcher | ||
} | ||
|
||
@Throws(IOException::class) | ||
fun shutdown() { | ||
mockWebServer.shutdown() | ||
} | ||
|
||
fun url(path: String): HttpUrl = mockWebServer.url(path) | ||
fun enqueueResponse(response: MockResponse) = (dispatcher as MockOAuth2Dispatcher).enqueueResponse(response) | ||
fun enqueueCallback(oAuth2TokenCallback: OAuth2TokenCallback) = (dispatcher as MockOAuth2Dispatcher).enqueueTokenCallback(oAuth2TokenCallback) | ||
fun takeRequest(): RecordedRequest = mockWebServer.takeRequest() | ||
|
||
fun wellKnownUrl(issuerId: String): HttpUrl = mockWebServer.url(issuerId).toWellKnownUrl() | ||
fun tokenEndpointUrl(issuerId: String): HttpUrl = mockWebServer.url(issuerId).toTokenEndpointUrl() | ||
fun jwksUrl(issuerId: String): HttpUrl = mockWebServer.url(issuerId).toJwksUrl() | ||
fun issuerUrl(issuerId: String): HttpUrl = mockWebServer.url(issuerId) | ||
fun authorizationEndpointUrl(issuerId: String): HttpUrl = mockWebServer.url(issuerId).toAuthorizationEndpointUrl() | ||
fun baseUrl(): HttpUrl = mockWebServer.url("") | ||
|
||
fun issueToken(issuerId: String, clientId: String, OAuth2TokenCallback: OAuth2TokenCallback): SignedJWT { | ||
val uri = tokenEndpointUrl(issuerId) | ||
val issuerUrl = issuerUrl(issuerId) | ||
val tokenRequest = TokenRequest( | ||
uri.toUri(), | ||
ClientSecretBasic(ClientID(clientId), Secret("secret")), | ||
AuthorizationCodeGrant(AuthorizationCode("123"), URI.create("http://localhost")) | ||
) | ||
return tokenProvider.accessToken(tokenRequest, issuerUrl, null, OAuth2TokenCallback) | ||
} | ||
} | ||
|
||
class MockOAuth2Dispatcher( | ||
config: OAuth2Config | ||
) : Dispatcher() { | ||
private val httpRequestHandler: OAuth2HttpRequestHandler = OAuth2HttpRequestHandler(config) | ||
private val responseQueue: BlockingQueue<MockResponse> = LinkedBlockingQueue() | ||
|
||
fun enqueueResponse(mockResponse: MockResponse) = responseQueue.add(mockResponse) | ||
fun enqueueTokenCallback(oAuth2TokenCallback: OAuth2TokenCallback) = httpRequestHandler.enqueueTokenCallback(oAuth2TokenCallback) | ||
|
||
override fun dispatch(request: RecordedRequest): MockResponse = | ||
when { | ||
responseQueue.peek() != null -> responseQueue.take() | ||
else -> mockResponse(httpRequestHandler.handleRequest(request.asOAuth2HttpRequest())) | ||
} | ||
|
||
|
||
private fun mockResponse(response: OAuth2HttpResponse): MockResponse = | ||
MockResponse() | ||
.setHeaders(response.headers) | ||
.setResponseCode(response.status) | ||
.apply { | ||
response.body?.let { this.setBody(it) } | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
src/main/kotlin/no/nav/security/mock/oauth2/OAuth2Config.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package no.nav.security.mock.oauth2 | ||
|
||
import no.nav.security.mock.oauth2.token.OAuth2TokenCallback | ||
import no.nav.security.mock.oauth2.token.OAuth2TokenProvider | ||
|
||
data class OAuth2Config( | ||
val interactiveLogin: Boolean = false, | ||
val tokenProvider: OAuth2TokenProvider = OAuth2TokenProvider(), | ||
val oAuth2TokenCallbacks: Set<OAuth2TokenCallback> = emptySet() | ||
) |
Oops, something went wrong.