Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ data class ClientConfiguration(
var clientSecret: String? = null,
var scopes: Set<String> = setOf(),
var redirectUris: Set<String> = setOf(),
var oauthFlows: Set<String> = setOf()
var authorizedGrantTypes: Set<String> = setOf()
)
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class InMemoryClient : ClientService {

override fun clientOf(clientId: String): Client? {
return clients.filter { it.clientId == clientId }
.map { client -> nl.myndocs.oauth2.client.Client(client.clientId!!, client.scopes, client.redirectUris) }
.map { client -> nl.myndocs.oauth2.client.Client(client.clientId!!, client.scopes, client.redirectUris, client.authorizedGrantTypes) }
.firstOrNull()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package nl.myndocs.oauth2

import nl.myndocs.oauth2.authenticator.Authenticator
import nl.myndocs.oauth2.authenticator.IdentityScopeVerifier
import nl.myndocs.oauth2.client.AuthorizedGrantType
import nl.myndocs.oauth2.client.Client
import nl.myndocs.oauth2.client.ClientService
import nl.myndocs.oauth2.exception.*
Expand Down Expand Up @@ -46,6 +47,12 @@ class Oauth2TokenService(
val requestedClient = clientService.clientOf(
passwordGrantRequest.clientId!!
)!!

val authorizedGrantType = AuthorizedGrantType.PASSWORD
if (!requestedClient.authorizedGrantTypes.contains(authorizedGrantType)) {
throw InvalidGrantException("Authorize not allowed: '$authorizedGrantType'")
}

val requestedIdentity = identityService.identityOf(
requestedClient, passwordGrantRequest.username
)
Expand Down Expand Up @@ -127,6 +134,13 @@ class Oauth2TokenService(
throw InvalidGrantException()
}

val client = clientService.clientOf(refreshToken.clientId)!!

val authorizedGrantType = AuthorizedGrantType.REFRESH_TOKEN
if (!client.authorizedGrantTypes.contains(authorizedGrantType)) {
throw InvalidGrantException("Authorize not allowed: '$authorizedGrantType'")
}

val accessToken = accessTokenConverter.convertToToken(
refreshToken.username,
refreshToken.clientId,
Expand Down Expand Up @@ -165,6 +179,11 @@ class Oauth2TokenService(
throw InvalidGrantException("invalid 'redirect_uri'")
}

val authorizedGrantType = AuthorizedGrantType.AUTHORIZATION_CODE
if (!clientOf.authorizedGrantTypes.contains(authorizedGrantType)) {
throw InvalidGrantException("Authorize not allowed: '$authorizedGrantType'")
}

val identityOf = identityService.identityOf(clientOf, redirect.username) ?: throw InvalidIdentityException()

var validIdentity = authenticator?.validCredentials(clientOf, identityOf, redirect.password)
Expand Down Expand Up @@ -220,6 +239,11 @@ class Oauth2TokenService(
throw InvalidGrantException("invalid 'redirect_uri'")
}

val authorizedGrantType = AuthorizedGrantType.IMPLICIT
if (!clientOf.authorizedGrantTypes.contains(authorizedGrantType)) {
throw InvalidGrantException("Authorize not allowed: '$authorizedGrantType'")
}

val identityOf = identityService.identityOf(clientOf, redirect.username) ?: throw InvalidIdentityException()

var validIdentity = authenticator?.validCredentials(clientOf, identityOf, redirect.password)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package nl.myndocs.oauth2.client

object AuthorizedGrantType {
const val IMPLICIT = "implicit"
const val REFRESH_TOKEN = "refresh_token"
const val PASSWORD = "password"
const val AUTHORIZATION_CODE = "authorization_code"
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ package nl.myndocs.oauth2.client
data class Client(
val clientId: String,
val clientScopes: Set<String>,
val redirectUris: Set<String>
val redirectUris: Set<String>,
val authorizedGrantTypes: Set<String>
)
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import io.mockk.impl.annotations.InjectMockKs
import io.mockk.impl.annotations.MockK
import io.mockk.impl.annotations.RelaxedMockK
import io.mockk.junit5.MockKExtension
import nl.myndocs.oauth2.client.AuthorizedGrantType
import nl.myndocs.oauth2.client.Client
import nl.myndocs.oauth2.client.ClientService
import nl.myndocs.oauth2.exception.InvalidClientException
Expand Down Expand Up @@ -60,7 +61,7 @@ internal class AuthorizationCodeGrantTokenServiceTest {
fun validAuthorizationCodeGrant() {
val requestScopes = setOf("scope1")

val client = Client(clientId, setOf("scope1", "scope2"), setOf())
val client = Client(clientId, setOf("scope1", "scope2"), setOf(), setOf(AuthorizedGrantType.AUTHORIZATION_CODE))
val identity = Identity(username)
val codeToken = CodeToken(code, Instant.now(), username, clientId, redirectUri, requestScopes)

Expand Down Expand Up @@ -88,7 +89,7 @@ internal class AuthorizationCodeGrantTokenServiceTest {

@Test
fun invalidClientException() {
val client = Client(clientId, setOf(), setOf())
val client = Client(clientId, setOf(), setOf(), setOf(AuthorizedGrantType.AUTHORIZATION_CODE))
every { clientService.clientOf(clientId) } returns client
every { clientService.validClient(client, clientSecret) } returns false

Expand All @@ -106,7 +107,7 @@ internal class AuthorizationCodeGrantTokenServiceTest {
redirectUri
)

val client = Client(clientId, setOf(), setOf())
val client = Client(clientId, setOf(), setOf(), setOf(AuthorizedGrantType.AUTHORIZATION_CODE))
every { clientService.clientOf(clientId) } returns client
every { clientService.validClient(client, clientSecret) } returns true

Expand All @@ -124,7 +125,7 @@ internal class AuthorizationCodeGrantTokenServiceTest {
null
)

val client = Client(clientId, setOf(), setOf())
val client = Client(clientId, setOf(), setOf(), setOf(AuthorizedGrantType.AUTHORIZATION_CODE))
every { clientService.clientOf(clientId) } returns client
every { clientService.validClient(client, clientSecret) } returns true

Expand All @@ -138,7 +139,7 @@ internal class AuthorizationCodeGrantTokenServiceTest {
val wrongRedirectUri = ""
val requestScopes = setOf("scope1")

val client = Client(clientId, setOf("scope1", "scope2"), setOf())
val client = Client(clientId, setOf("scope1", "scope2"), setOf(), setOf(AuthorizedGrantType.AUTHORIZATION_CODE))
val codeToken = CodeToken(code, Instant.now(), username, clientId, wrongRedirectUri, requestScopes)

val refreshToken = RefreshToken("test", Instant.now(), username, clientId, requestScopes)
Expand All @@ -157,7 +158,7 @@ internal class AuthorizationCodeGrantTokenServiceTest {

@Test
fun invalidCodeException() {
val client = Client(clientId, setOf("scope1", "scope2"), setOf())
val client = Client(clientId, setOf("scope1", "scope2"), setOf(), setOf(AuthorizedGrantType.AUTHORIZATION_CODE))

every { clientService.clientOf(clientId) } returns client
every { clientService.validClient(client, clientSecret) } returns true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import io.mockk.impl.annotations.MockK
import io.mockk.impl.annotations.RelaxedMockK
import io.mockk.junit5.MockKExtension
import io.mockk.verify
import nl.myndocs.oauth2.client.AuthorizedGrantType
import nl.myndocs.oauth2.client.Client
import nl.myndocs.oauth2.client.ClientService
import nl.myndocs.oauth2.exception.InvalidClientException
Expand Down Expand Up @@ -61,7 +62,7 @@ internal class PasswordGrantTokenServiceTest {

@Test
fun validPasswordGrant() {
val client = Client(clientId, setOf("scope1", "scope2"), setOf())
val client = Client(clientId, setOf("scope1", "scope2"), setOf(), setOf(AuthorizedGrantType.PASSWORD))
val identity = Identity(username)
val requestScopes = setOf("scope1")
val refreshToken = RefreshToken("test", Instant.now(), username, clientId, requestScopes)
Expand Down Expand Up @@ -91,7 +92,7 @@ internal class PasswordGrantTokenServiceTest {

@Test
fun invalidClientException() {
val client = Client(clientId, setOf(), setOf())
val client = Client(clientId, setOf(), setOf(), setOf(AuthorizedGrantType.PASSWORD))
every { clientService.clientOf(clientId) } returns client
every { clientService.validClient(client, clientSecret) } returns false

Expand All @@ -110,7 +111,7 @@ internal class PasswordGrantTokenServiceTest {
scope
)

val client = Client(clientId, setOf(), setOf())
val client = Client(clientId, setOf(), setOf(), setOf(AuthorizedGrantType.PASSWORD))
every { clientService.clientOf(clientId) } returns client
every { clientService.validClient(client, clientSecret) } returns true

Expand All @@ -129,7 +130,7 @@ internal class PasswordGrantTokenServiceTest {
scope
)

val client = Client(clientId, setOf(), setOf())
val client = Client(clientId, setOf(), setOf(), setOf(AuthorizedGrantType.PASSWORD))
every { clientService.clientOf(clientId) } returns client
every { clientService.validClient(client, clientSecret) } returns true

Expand All @@ -140,7 +141,7 @@ internal class PasswordGrantTokenServiceTest {

@Test
fun invalidIdentityException() {
val client = Client(clientId, setOf(), setOf())
val client = Client(clientId, setOf(), setOf(), setOf(AuthorizedGrantType.PASSWORD))
val identity = Identity(username)

every { clientService.clientOf(clientId) } returns client
Expand All @@ -155,7 +156,7 @@ internal class PasswordGrantTokenServiceTest {

@Test
fun invalidIdentityScopeException() {
val client = Client(clientId, setOf("scope1", "scope2"), setOf())
val client = Client(clientId, setOf("scope1", "scope2"), setOf(), setOf(AuthorizedGrantType.PASSWORD))
val identity = Identity(username)

every { clientService.clientOf(clientId) } returns client
Expand All @@ -171,7 +172,7 @@ internal class PasswordGrantTokenServiceTest {

@Test
fun invalidRequestClientScopeException() {
val client = Client(clientId, setOf("scope3"), setOf())
val client = Client(clientId, setOf("scope3"), setOf(), setOf(AuthorizedGrantType.PASSWORD))
val identity = Identity(username)

every { clientService.clientOf(clientId) } returns client
Expand All @@ -195,7 +196,7 @@ internal class PasswordGrantTokenServiceTest {
null
)

val client = Client(clientId, setOf("scope1", "scope2"), setOf())
val client = Client(clientId, setOf("scope1", "scope2"), setOf(), setOf(AuthorizedGrantType.PASSWORD))
val identity = Identity(username)
val requestScopes = setOf("scope1", "scope2")
val refreshToken = RefreshToken("test", Instant.now(), username, clientId, requestScopes)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import io.mockk.impl.annotations.MockK
import io.mockk.impl.annotations.RelaxedMockK
import io.mockk.junit5.MockKExtension
import io.mockk.verify
import nl.myndocs.oauth2.client.AuthorizedGrantType
import nl.myndocs.oauth2.client.Client
import nl.myndocs.oauth2.client.ClientService
import nl.myndocs.oauth2.exception.InvalidClientException
Expand Down Expand Up @@ -58,7 +59,7 @@ internal class RefreshTokenGrantTokenServiceTest {

@Test
fun validRefreshToken() {
val client = Client(clientId, setOf("scope1", "scope2"), setOf())
val client = Client(clientId, setOf("scope1", "scope2"), setOf(), setOf(AuthorizedGrantType.REFRESH_TOKEN))
val token = RefreshToken("test", Instant.now(), username, clientId, scopes)
val newRefreshToken = RefreshToken("test", Instant.now(), username, clientId, scopes)
val accessToken = AccessToken("test", "bearer", Instant.now(), username, clientId, scopes, newRefreshToken)
Expand All @@ -79,7 +80,7 @@ internal class RefreshTokenGrantTokenServiceTest {

@Test
fun missingRefreshToken() {
val client = Client(clientId, setOf("scope1", "scope2"), setOf())
val client = Client(clientId, setOf("scope1", "scope2"), setOf(), setOf(AuthorizedGrantType.REFRESH_TOKEN))

every { clientService.clientOf(clientId) } returns client
every { clientService.validClient(client, clientSecret) } returns true
Expand All @@ -106,7 +107,7 @@ internal class RefreshTokenGrantTokenServiceTest {

@Test
fun invalidClientException() {
val client = Client(clientId, setOf(), setOf())
val client = Client(clientId, setOf(), setOf(), setOf(AuthorizedGrantType.REFRESH_TOKEN))
every { clientService.clientOf(clientId) } returns client
every { clientService.validClient(client, clientSecret) } returns false

Expand All @@ -117,7 +118,7 @@ internal class RefreshTokenGrantTokenServiceTest {

@Test
fun storedClientDoesNotMatchRequestedException() {
val client = Client(clientId, setOf("scope1", "scope2"), setOf())
val client = Client(clientId, setOf("scope1", "scope2"), setOf(), setOf(AuthorizedGrantType.REFRESH_TOKEN))
val token = RefreshToken("test", Instant.now(), username, "wrong-client", scopes)

every { clientService.clientOf(clientId) } returns client
Expand Down