1+ package nl.myndocs.oauth2
2+
3+ import io.mockk.every
4+ import io.mockk.impl.annotations.InjectMockKs
5+ import io.mockk.impl.annotations.MockK
6+ import io.mockk.impl.annotations.RelaxedMockK
7+ import io.mockk.junit5.MockKExtension
8+ import nl.myndocs.oauth2.client.Client
9+ import nl.myndocs.oauth2.client.ClientService
10+ import nl.myndocs.oauth2.exception.InvalidClientException
11+ import nl.myndocs.oauth2.exception.InvalidGrantException
12+ import nl.myndocs.oauth2.exception.InvalidRequestException
13+ import nl.myndocs.oauth2.identity.IdentityService
14+ import nl.myndocs.oauth2.request.AuthorizationCodeRequest
15+ import nl.myndocs.oauth2.token.AccessToken
16+ import nl.myndocs.oauth2.token.CodeToken
17+ import nl.myndocs.oauth2.token.RefreshToken
18+ import nl.myndocs.oauth2.token.TokenStore
19+ import nl.myndocs.oauth2.token.converter.AccessTokenConverter
20+ import nl.myndocs.oauth2.token.converter.CodeTokenConverter
21+ import nl.myndocs.oauth2.token.converter.RefreshTokenConverter
22+ import org.junit.jupiter.api.Assertions.assertThrows
23+ import org.junit.jupiter.api.Test
24+ import org.junit.jupiter.api.extension.ExtendWith
25+ import java.time.Instant
26+
27+ @ExtendWith(MockKExtension ::class )
28+ internal class AuthorizationCodeGrantTokenServiceTest {
29+ @MockK
30+ lateinit var identityService: IdentityService
31+ @MockK
32+ lateinit var clientService: ClientService
33+ @RelaxedMockK
34+ lateinit var tokenStore: TokenStore
35+ @MockK
36+ lateinit var accessTokenConverter: AccessTokenConverter
37+ @MockK
38+ lateinit var refreshTokenConverter: RefreshTokenConverter
39+ @MockK
40+ lateinit var codeTokenConverter: CodeTokenConverter
41+
42+ @InjectMockKs
43+ lateinit var tokenService: TokenService
44+
45+ val clientId = " client-foo"
46+ val clientSecret = " client-bar"
47+ val code = " user-foo"
48+ val redirectUri = " http://foo.lcoalhost"
49+ val username = " user-foo"
50+
51+ val authorizationCodeRequest = AuthorizationCodeRequest (
52+ clientId,
53+ clientSecret,
54+ code,
55+ redirectUri
56+ )
57+
58+ @Test
59+ fun validAuthorizationCodeGrant () {
60+ val requestScopes = setOf (" scope1" )
61+
62+ val client = Client (clientId, setOf (" scope1" , " scope2" ), setOf ())
63+ val codeToken = CodeToken (code, Instant .now(), username, clientId, redirectUri, requestScopes)
64+
65+ val refreshToken = RefreshToken (" test" , Instant .now(), username, clientId, requestScopes)
66+ val accessToken = AccessToken (" test" , " bearer" , Instant .now(), username, clientId, requestScopes, refreshToken)
67+
68+ every { clientService.clientOf(clientId) } returns client
69+ every { clientService.validClient(client, clientSecret) } returns true
70+ every { tokenStore.consumeCodeToken(code) } returns codeToken
71+ every { refreshTokenConverter.convertToToken(username, clientId, requestScopes) } returns refreshToken
72+ every { accessTokenConverter.convertToToken(username, clientId, requestScopes, refreshToken) } returns accessToken
73+
74+ tokenService.authorize(authorizationCodeRequest)
75+ }
76+
77+ @Test
78+ fun nonExistingClientException () {
79+ every { clientService.clientOf(clientId) } returns null
80+
81+ assertThrows(
82+ InvalidClientException ::class .java
83+ ) { tokenService.authorize(authorizationCodeRequest) }
84+ }
85+
86+ @Test
87+ fun invalidClientException () {
88+ val client = Client (clientId, setOf (), setOf ())
89+ every { clientService.clientOf(clientId) } returns client
90+ every { clientService.validClient(client, clientSecret) } returns false
91+
92+ assertThrows(
93+ InvalidClientException ::class .java
94+ ) { tokenService.authorize(authorizationCodeRequest) }
95+ }
96+
97+ @Test
98+ fun missingCodeException () {
99+ val authorizationCodeRequest = AuthorizationCodeRequest (
100+ clientId,
101+ clientSecret,
102+ null ,
103+ redirectUri
104+ )
105+
106+ val client = Client (clientId, setOf (), setOf ())
107+ every { clientService.clientOf(clientId) } returns client
108+ every { clientService.validClient(client, clientSecret) } returns true
109+
110+ assertThrows(
111+ InvalidRequestException ::class .java
112+ ) { tokenService.authorize(authorizationCodeRequest) }
113+ }
114+
115+ @Test
116+ fun missingRedirectUriException () {
117+ val authorizationCodeRequest = AuthorizationCodeRequest (
118+ clientId,
119+ clientSecret,
120+ code,
121+ null
122+ )
123+
124+ val client = Client (clientId, setOf (), setOf ())
125+ every { clientService.clientOf(clientId) } returns client
126+ every { clientService.validClient(client, clientSecret) } returns true
127+
128+ assertThrows(
129+ InvalidRequestException ::class .java
130+ ) { tokenService.authorize(authorizationCodeRequest) }
131+ }
132+
133+ @Test
134+ fun invalidRedirectUriException () {
135+ val wrongRedirectUri = " "
136+ val requestScopes = setOf (" scope1" )
137+
138+ val client = Client (clientId, setOf (" scope1" , " scope2" ), setOf ())
139+ val codeToken = CodeToken (code, Instant .now(), username, clientId, wrongRedirectUri, requestScopes)
140+
141+ val refreshToken = RefreshToken (" test" , Instant .now(), username, clientId, requestScopes)
142+ val accessToken = AccessToken (" test" , " bearer" , Instant .now(), username, clientId, requestScopes, refreshToken)
143+
144+ every { clientService.clientOf(clientId) } returns client
145+ every { clientService.validClient(client, clientSecret) } returns true
146+ every { tokenStore.consumeCodeToken(code) } returns codeToken
147+ every { refreshTokenConverter.convertToToken(username, clientId, requestScopes) } returns refreshToken
148+ every { accessTokenConverter.convertToToken(username, clientId, requestScopes, refreshToken) } returns accessToken
149+
150+ assertThrows(
151+ InvalidGrantException ::class .java
152+ ) { tokenService.authorize(authorizationCodeRequest) }
153+ }
154+
155+ @Test
156+ fun invalidCodeException () {
157+ val client = Client (clientId, setOf (" scope1" , " scope2" ), setOf ())
158+
159+ every { clientService.clientOf(clientId) } returns client
160+ every { clientService.validClient(client, clientSecret) } returns true
161+ every { tokenStore.consumeCodeToken(code) } returns null
162+
163+ assertThrows(
164+ InvalidGrantException ::class .java
165+ ) { tokenService.authorize(authorizationCodeRequest) }
166+ }
167+
168+ }
0 commit comments