Skip to content

Commit da62c31

Browse files
henriquels25jzheaux
authored andcommitted
Add test examples for the resource server sample
- Add a post endpoint in /messages - Changes the security config to require the read scope to GET a message and the write scope to POST a new message. - Changes the jwks of the mock server so I could create a new access token with the write scope. - Creates tests and integration-tests for the POST endpoint. - Changes the README to add an example of a POST request. Fixes gh-7118
1 parent 646f257 commit da62c31

File tree

6 files changed

+104
-12
lines changed

6 files changed

+104
-12
lines changed

samples/boot/oauth2resourceserver/README.adoc

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ Or import the project into your IDE and run `OAuth2ResourceServerApplication` fr
4444
Once it is up, you can use the following token:
4545

4646
```bash
47-
export TOKEN=eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJzdWJqZWN0IiwiZXhwIjo0NjgzODA1MTI4fQ.ULEPdHG-MK5GlrTQMhgqcyug2brTIZaJIrahUeq9zaiwUSdW83fJ7W1IDd2Z3n4a25JY2uhEcoV95lMfccHR6y_2DLrNvfta22SumY9PEDF2pido54LXG6edIGgarnUbJdR4rpRe_5oRGVa8gDx8FnuZsNv6StSZHAzw5OsuevSTJ1UbJm4UfX3wiahFOQ2OI6G-r5TB2rQNdiPHuNyzG5yznUqRIZ7-GCoMqHMaC-1epKxiX8gYXRROuUYTtcMNa86wh7OVDmvwVmFioRcR58UWBRoO1XQexTtOQq_t8KYsrPZhb9gkyW8x2bAQF-d0J0EJY8JslaH6n4RBaZISww
47+
export TOKEN=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzdWJqZWN0IiwiZXhwIjoyMTY0MjQ1ODgwLCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiMDFkOThlZWEtNjc0MC00OGRlLTk4ODAtYzM5ZjgyMGZiNzVlIiwiY2xpZW50X2lkIjoibm9zY29wZXMiLCJzY29wZSI6WyJub25lIl19.VOzgGLOUuQ_R2Ur1Ke41VaobddhKgUZgto7Y3AGxst7SuxLQ4LgWwdSSDRx-jRvypjsCgYPbjAYLhn9nCbfwtCitkymUKUNKdebvVAI0y8YvliWTL5S-GiJD9dN8SSsXUla9A4xB_9Mt5JAlRpQotQSCLojVSKQmjhMpQWmYAlKVjnlImoRwQFPI4w3Ijn4G4EMTKWUYRfrD0-WNT9ZYWBeza6QgV6sraP7ToRB3eQLy2p04cU40X-RHLeYCsMBfxsMMh89CJff-9tn7VDKi1hAGc_Lp9yS9ZaItJuFJTjf8S_vsjVB1nBhvdS_6IED_m_fOU52KiGSO2qL6shxHvg
4848
```
4949

5050
And then make this request:
@@ -61,10 +61,10 @@ Hello, subject!
6161

6262
where `subject` is the value of the `sub` field in the JWT returned by the Authorization Server.
6363

64-
Or this:
64+
Or this to make a GET request to /messages:
6565

6666
```bash
67-
export TOKEN=eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJzdWJqZWN0Iiwic2NvcGUiOiJtZXNzYWdlOnJlYWQiLCJleHAiOjQ2ODM4MDUxNDF9.h-j6FKRFdnTdmAueTZCdep45e6DPwqM68ZQ8doIJ1exi9YxAlbWzOwId6Bd0L5YmCmp63gGQgsBUBLzwnZQ8kLUgUOBEC3UzSWGRqMskCY9_k9pX0iomX6IfF3N0PaYs0WPC4hO1s8wfZQ-6hKQ4KigFi13G9LMLdH58PRMK0pKEvs3gCbHJuEPw-K5ORlpdnleUTQIwINafU57cmK3KocTeknPAM_L716sCuSYGvDl6xUTXO7oPdrXhS_EhxLP6KxrpI1uD4Ea_5OWTh7S0Wx5LLDfU6wBG1DowN20d374zepOIEkR-Jnmr_QlR44vmRqS5ncrF-1R0EGcPX49U6A
67+
export TOKEN=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzdWJqZWN0IiwiZXhwIjoyMTY0MjQ1NjQ4LCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiY2I1ZGMwNDYtMDkyMi00ZGJmLWE5MzAtOGI2M2FhZTYzZjk2IiwiY2xpZW50X2lkIjoicmVhZGVyIiwic2NvcGUiOlsibWVzc2FnZTpyZWFkIl19.Pre2ksnMiOGYWQtuIgHB0i3uTnNzD0SMFM34iyQJHK5RLlSjge08s9qHdx6uv5cZ4gZm_cB1D6f4-fLx76bCblK6mVcabbR74w_eCdSBXNXuqG-HNrOYYmmx5iJtdwx5fXPmF8TyVzsq_LvRm_LN4lWNYquT4y36Tox6ZD3feYxXvHQ3XyZn9mVKnlzv-GCwkBohCR3yPow5uVmr04qh_al52VIwKMrvJBr44igr4fTZmzwRAZmQw5rZeyep0b4nsCjadNcndHtMtYKNVuG5zbDLsB7GGvilcI9TDDnUXtwthB_3iq32DAd9x8wJmJ5K8gmX6GjZFtYzKk_zEboXoQ
6868

6969
curl -H "Authorization: Bearer $TOKEN" localhost:8080/message
7070
```
@@ -75,6 +75,20 @@ Will respond with:
7575
secret message
7676
```
7777

78+
In order to make a POST request to /message, you can use the following request:
79+
80+
```bash
81+
export TOKEN=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzdWJqZWN0IiwiZXhwIjoyMTY0MjQzOTA0LCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiZGI4ZjgwMzQtM2VlNy00NjBjLTk3NTEtMDJiMDA1OWI5NzA4IiwiY2xpZW50X2lkIjoid3JpdGVyIiwic2NvcGUiOlsibWVzc2FnZTp3cml0ZSJdfQ.USvpx_ntKXtchLmc93auJq0qSav6vLm4B7ItPzhrDH2xmogBP35eKeklwXK5GCb7ck1aKJV5SpguBlTCz0bZC1zAWKB6gyFIqedALPAran5QR-8WpGfl0wFqds7d8Jw3xmpUUBduRLab9hkeAhgoVgxevc8d6ITM7kRnHo5wT3VzvBU8DquedVXm5fbBnRPgG4_jOWJKbqYpqaR2z2TnZRWh3CqL82Orh1Ww1dJYF_fae1dTVV4tvN5iSndYcGxMoBaiw3kRRi6EyNxnXnt1pFtZqc1f6D9x4AHiri8_vpBp2vwG5OfQD5-rrleP_XlIB3rNQT7tu3fiqu4vUzQaEg
82+
83+
curl -H "Authorization: Bearer $TOKEN" -d "my message" localhost:8080/message
84+
```
85+
86+
Will respond this:
87+
88+
```bash
89+
Message was created. Content: my message
90+
```
91+
7892
== 2. Testing against other Authorization Servers
7993

8094
_In order to use this sample, your Authorization Server must support JWTs that either use the "scope" or "scp" attribute._

samples/boot/oauth2resourceserver/src/integration-test/java/sample/OAuth2ResourceServerApplicationITests.java

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -30,6 +30,7 @@
3030

3131
import static org.hamcrest.Matchers.containsString;
3232
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
33+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
3334
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
3435
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
3536
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@@ -45,8 +46,9 @@
4546
@ActiveProfiles("test")
4647
public class OAuth2ResourceServerApplicationITests {
4748

48-
String noScopesToken = "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJzdWJqZWN0IiwiZXhwIjo0NjgzODA1MTI4fQ.ULEPdHG-MK5GlrTQMhgqcyug2brTIZaJIrahUeq9zaiwUSdW83fJ7W1IDd2Z3n4a25JY2uhEcoV95lMfccHR6y_2DLrNvfta22SumY9PEDF2pido54LXG6edIGgarnUbJdR4rpRe_5oRGVa8gDx8FnuZsNv6StSZHAzw5OsuevSTJ1UbJm4UfX3wiahFOQ2OI6G-r5TB2rQNdiPHuNyzG5yznUqRIZ7-GCoMqHMaC-1epKxiX8gYXRROuUYTtcMNa86wh7OVDmvwVmFioRcR58UWBRoO1XQexTtOQq_t8KYsrPZhb9gkyW8x2bAQF-d0J0EJY8JslaH6n4RBaZISww";
49-
String messageReadToken = "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJzdWJqZWN0Iiwic2NvcGUiOiJtZXNzYWdlOnJlYWQiLCJleHAiOjQ2ODM4MDUxNDF9.h-j6FKRFdnTdmAueTZCdep45e6DPwqM68ZQ8doIJ1exi9YxAlbWzOwId6Bd0L5YmCmp63gGQgsBUBLzwnZQ8kLUgUOBEC3UzSWGRqMskCY9_k9pX0iomX6IfF3N0PaYs0WPC4hO1s8wfZQ-6hKQ4KigFi13G9LMLdH58PRMK0pKEvs3gCbHJuEPw-K5ORlpdnleUTQIwINafU57cmK3KocTeknPAM_L716sCuSYGvDl6xUTXO7oPdrXhS_EhxLP6KxrpI1uD4Ea_5OWTh7S0Wx5LLDfU6wBG1DowN20d374zepOIEkR-Jnmr_QlR44vmRqS5ncrF-1R0EGcPX49U6A";
49+
String noScopesToken = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzdWJqZWN0IiwiZXhwIjoyMTY0MjQ1ODgwLCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiMDFkOThlZWEtNjc0MC00OGRlLTk4ODAtYzM5ZjgyMGZiNzVlIiwiY2xpZW50X2lkIjoibm9zY29wZXMiLCJzY29wZSI6WyJub25lIl19.VOzgGLOUuQ_R2Ur1Ke41VaobddhKgUZgto7Y3AGxst7SuxLQ4LgWwdSSDRx-jRvypjsCgYPbjAYLhn9nCbfwtCitkymUKUNKdebvVAI0y8YvliWTL5S-GiJD9dN8SSsXUla9A4xB_9Mt5JAlRpQotQSCLojVSKQmjhMpQWmYAlKVjnlImoRwQFPI4w3Ijn4G4EMTKWUYRfrD0-WNT9ZYWBeza6QgV6sraP7ToRB3eQLy2p04cU40X-RHLeYCsMBfxsMMh89CJff-9tn7VDKi1hAGc_Lp9yS9ZaItJuFJTjf8S_vsjVB1nBhvdS_6IED_m_fOU52KiGSO2qL6shxHvg";
50+
String messageReadToken = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzdWJqZWN0IiwiZXhwIjoyMTY0MjQ1NjQ4LCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiY2I1ZGMwNDYtMDkyMi00ZGJmLWE5MzAtOGI2M2FhZTYzZjk2IiwiY2xpZW50X2lkIjoicmVhZGVyIiwic2NvcGUiOlsibWVzc2FnZTpyZWFkIl19.Pre2ksnMiOGYWQtuIgHB0i3uTnNzD0SMFM34iyQJHK5RLlSjge08s9qHdx6uv5cZ4gZm_cB1D6f4-fLx76bCblK6mVcabbR74w_eCdSBXNXuqG-HNrOYYmmx5iJtdwx5fXPmF8TyVzsq_LvRm_LN4lWNYquT4y36Tox6ZD3feYxXvHQ3XyZn9mVKnlzv-GCwkBohCR3yPow5uVmr04qh_al52VIwKMrvJBr44igr4fTZmzwRAZmQw5rZeyep0b4nsCjadNcndHtMtYKNVuG5zbDLsB7GGvilcI9TDDnUXtwthB_3iq32DAd9x8wJmJ5K8gmX6GjZFtYzKk_zEboXoQ";
51+
String messageWriteToken = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzdWJqZWN0IiwiZXhwIjoyMTY0MjQzOTA0LCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiZGI4ZjgwMzQtM2VlNy00NjBjLTk3NTEtMDJiMDA1OWI5NzA4IiwiY2xpZW50X2lkIjoid3JpdGVyIiwic2NvcGUiOlsibWVzc2FnZTp3cml0ZSJdfQ.USvpx_ntKXtchLmc93auJq0qSav6vLm4B7ItPzhrDH2xmogBP35eKeklwXK5GCb7ck1aKJV5SpguBlTCz0bZC1zAWKB6gyFIqedALPAran5QR-8WpGfl0wFqds7d8Jw3xmpUUBduRLab9hkeAhgoVgxevc8d6ITM7kRnHo5wT3VzvBU8DquedVXm5fbBnRPgG4_jOWJKbqYpqaR2z2TnZRWh3CqL82Orh1Ww1dJYF_fae1dTVV4tvN5iSndYcGxMoBaiw3kRRi6EyNxnXnt1pFtZqc1f6D9x4AHiri8_vpBp2vwG5OfQD5-rrleP_XlIB3rNQT7tu3fiqu4vUzQaEg";
5052

5153
@Autowired
5254
MockMvc mvc;
@@ -81,6 +83,27 @@ public void performWhenInsufficientlyScopedBearerTokenThenDeniesScopedMethodAcce
8183
containsString("Bearer error=\"insufficient_scope\"")));
8284
}
8385

86+
@Test
87+
public void performPostWhenValidBearerTokenThenScopedRequestsAlsoWork()
88+
throws Exception {
89+
90+
this.mvc.perform(post("/message").content("example message")
91+
.with(bearerToken(this.messageWriteToken)))
92+
.andExpect(status().isOk())
93+
.andExpect(content().string(containsString("Message was created")));
94+
}
95+
96+
@Test
97+
public void performPostWhenInsufficientlyScopedBearerTokenThenDeniesScopedMethodAccess()
98+
throws Exception {
99+
100+
this.mvc.perform(post("/message").content("Example message")
101+
.with(bearerToken(this.messageReadToken)))
102+
.andExpect(status().isForbidden())
103+
.andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE,
104+
containsString("Bearer error=\"insufficient_scope\"")));
105+
}
106+
84107
private static class BearerTokenRequestPostProcessor implements RequestPostProcessor {
85108
private String token;
86109

samples/boot/oauth2resourceserver/src/main/java/org/springframework/boot/env/MockWebServerPropertySource.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -36,7 +36,7 @@ public class MockWebServerPropertySource extends PropertySource<MockWebServer> i
3636
DisposableBean {
3737

3838
private static final MockResponse JWKS_RESPONSE = response(
39-
"{\"keys\":[{\"p\":\"2p-ViY7DE9ZrdWQb544m0Jp7Cv03YCSljqfim9pD4ALhObX0OrAznOiowTjwBky9JGffMwDBVSfJSD9TSU7aH2sbbfi0bZLMdekKAuimudXwUqPDxrrg0BCyvCYgLmKjbVT3zcdylWSog93CNTxGDPzauu-oc0XPNKCXnaDpNvE\",\"kty\":\"RSA\",\"q\":\"sP_QYavrpBvSJ86uoKVGj2AGl78CSsAtpf1ybSY5TwUlorXSdqapRbY69Y271b0aMLzlleUn9ZTBO1dlKV2_dw_lPADHVia8z3pxL-8sUhIXLsgj4acchMk4c9YX-sFh07xENnyZ-_TXm3llPLuL67HUfBC2eKe800TmCYVWc9U\",\"d\":\"bn1nFxCQT4KLTHqo8mo9HvHD0cRNRNdWcKNnnEQkCF6tKbt-ILRyQGP8O40axLd7CoNVG9c9p_-g4-2kwCtLJNv_STLtwfpCY7VN5o6-ZIpfTjiW6duoPrLWq64Hm_4LOBQTiZfUPcLhsuJRHbWqakj-kV_YbUyC2Ocf_dd8IAQcSrAU2SCcDebhDCWwRUFvaa9V5eq0851S9goaA-AJz-JXyePH6ZFr8JxmWkWxYZ5kdcMD-sm9ZbxE0CaEk32l4fE4hR-L8x2dDtjWA-ahKCZ091z-gV3HWtR2JOjvxoNRjxUo3UxaGiFJHWNIl0EYUJZu1Cb-5wIlEI7wPx5mwQ\",\"e\":\"AQAB\",\"use\":\"sig\",\"kid\":\"one\",\"qi\":\"qS0OK48M2CIAA6_4Wdw4EbCaAfcTLf5Oy9t5BOF_PFUKqoSpZ6JsT5H0a_4zkjt-oI969v78OTlvBKbmEyKO-KeytzHBAA5CsLmVcz0THrMSg6oXZqu66MPnvWoZN9FEN5TklPOvBFm8Bg1QZ3k-YMVaM--DLvhaYR95_mqaz50\",\"dp\":\"Too2NozLGD1XrXyhabZvy1E0EuaVFj0UHQPDLSpkZ_2g3BK6Art6T0xmE8RYtmqrKIEIdlI3IliAvyvAx_1D7zWTTRaj-xlZyqJFrnXWL7zj8UxT8PkB-r2E-ILZ3NAi1gxIWezlBTZ8M6NfObDFmbTc_3tJkN_raISo8z_ziIE\",\"dq\":\"U0yhSkY5yOsa9YcMoigGVBWSJLpNHtbg5NypjHrPv8OhWbkOSq7WvSstBkFk5AtyFvvfZLMLIkWWxxGzV0t6f1MoxBtttLrYYyCxwihiiGFhLbAdSuZ1wnxcqA9bC7UVECvrQmVTpsMs8UupfHKbQBpZ8OWAqrnuYNNtG4_4Bt0\",\"n\":\"lygtuZj0lJjqOqIWocF8Bb583QDdq-aaFg8PesOp2-EDda6GqCpL-_NZVOflNGX7XIgjsWHcPsQHsV9gWuOzSJ0iEuWvtQ6eGBP5M6m7pccLNZfwUse8Cb4Ngx3XiTlyuqM7pv0LPyppZusfEHVEdeelou7Dy9k0OQ_nJTI3b2E1WBoHC58CJ453lo4gcBm1efURN3LIVc1V9NQY_ESBKVdwqYyoJPEanURLVGRd6cQKn6YrCbbIRHjqAyqOE-z3KmgDJnPriljfR5XhSGyM9eqD9Xpy6zu_MAeMJJfSArp857zLPk-Wf5VP9STAcjyfdBIybMKnwBYr2qHMT675hQ\"}]}",
39+
"{ \"keys\": [ { \"kty\": \"RSA\", \"e\": \"AQAB\", \"n\": \"jvBtqsGCOmnYzwe_-HvgOqlKk6HPiLEzS6uCCcnVkFXrhnkPMZ-uQXTR0u-7ZklF0XC7-AMW8FQDOJS1T7IyJpCyeU4lS8RIf_Z8RX51gPGnQWkRvNw61RfiSuSA45LR5NrFTAAGoXUca_lZnbqnl0td-6hBDVeHYkkpAsSck1NPhlcsn-Pvc2Vleui_Iy1U2mzZCM1Vx6Dy7x9IeP_rTNtDhULDMFbB_JYs-Dg6Zd5Ounb3mP57tBGhLYN7zJkN1AAaBYkElsc4GUsGsUWKqgteQSXZorpf6HdSJsQMZBDd7xG8zDDJ28hGjJSgWBndRGSzQEYU09Xbtzk-8khPuw\" } ] }",
4040
200
4141
);
4242

samples/boot/oauth2resourceserver/src/main/java/sample/OAuth2ResourceServerController.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,6 +18,8 @@
1818
import org.springframework.security.core.annotation.AuthenticationPrincipal;
1919
import org.springframework.security.oauth2.jwt.Jwt;
2020
import org.springframework.web.bind.annotation.GetMapping;
21+
import org.springframework.web.bind.annotation.PostMapping;
22+
import org.springframework.web.bind.annotation.RequestBody;
2123
import org.springframework.web.bind.annotation.RestController;
2224

2325
/**
@@ -35,4 +37,9 @@ public String index(@AuthenticationPrincipal Jwt jwt) {
3537
public String message() {
3638
return "secret message";
3739
}
40+
41+
@PostMapping("/message")
42+
public String createMessage(@RequestBody String message) {
43+
return String.format("Message was created. Content: %s", message);
44+
}
3845
}

samples/boot/oauth2resourceserver/src/main/java/sample/OAuth2ResourceServerSecurityConfiguration.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
1919
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
2020
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
21+
import org.springframework.http.HttpMethod;
2122

2223
import static org.springframework.security.config.Customizer.withDefaults;
2324

@@ -33,7 +34,8 @@ protected void configure(HttpSecurity http) throws Exception {
3334
http
3435
.authorizeRequests(authorizeRequests ->
3536
authorizeRequests
36-
.antMatchers("/message/**").hasAuthority("SCOPE_message:read")
37+
.antMatchers(HttpMethod.GET, "/message/**").hasAuthority("SCOPE_message:read")
38+
.antMatchers(HttpMethod.POST, "/message/**").hasAuthority("SCOPE_message:write")
3739
.anyRequest().authenticated()
3840
)
3941
.oauth2ResourceServer(oauth2ResourceServer ->

samples/boot/oauth2resourceserver/src/test/java/sample/OAuth2ResourceServerControllerTests.java

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,16 @@
2525
import org.springframework.security.oauth2.jwt.JwtDecoder;
2626
import org.springframework.test.context.junit4.SpringRunner;
2727
import org.springframework.test.web.servlet.MockMvc;
28+
import org.springframework.security.oauth2.jwt.Jwt;
2829

2930
import static org.hamcrest.CoreMatchers.is;
3031
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.jwt;
3132
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
33+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
3234
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
3335
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
36+
import static org.mockito.ArgumentMatchers.anyString;
37+
import static org.mockito.Mockito.when;
3438

3539
/**
3640
*
@@ -60,13 +64,55 @@ public void messageCanBeReadWithScopeMessageReadAuthority() throws Exception {
6064
mockMvc.perform(get("/message").with(jwt(jwt -> jwt.claim("scope", "message:read"))))
6165
.andExpect(content().string(is("secret message")));
6266

63-
mockMvc.perform(get("/message").with(jwt().authorities(new SimpleGrantedAuthority(("SCOPE_message:read")))))
64-
.andExpect(content().string(is("secret message")));
67+
mockMvc.perform(get("/message")
68+
.with(jwt().authorities(new SimpleGrantedAuthority(("SCOPE_message:read")))))
69+
.andExpect(content().string(is("secret message")));
6570
}
6671

6772
@Test
6873
public void messageCanNotBeReadWithoutScopeMessageReadAuthority() throws Exception {
6974
mockMvc.perform(get("/message").with(jwt()))
7075
.andExpect(status().isForbidden());
7176
}
77+
78+
@Test
79+
public void messageCanNotBeCreatedWithoutAnyScope() throws Exception {
80+
Jwt jwt = Jwt.withTokenValue("token")
81+
.header("alg", "none")
82+
.claim("scope", "")
83+
.build();
84+
when(jwtDecoder.decode(anyString())).thenReturn(jwt);
85+
mockMvc.perform(post("/message")
86+
.content("Hello message")
87+
.header("Authorization", "Bearer " + jwt.getTokenValue()))
88+
.andExpect(status().isForbidden());
89+
}
90+
91+
@Test
92+
public void messageCanNotBeCreatedWithScopeMessageReadAuthority() throws Exception {
93+
Jwt jwt = Jwt.withTokenValue("token")
94+
.header("alg", "none")
95+
.claim("scope", "message:read")
96+
.build();
97+
when(jwtDecoder.decode(anyString())).thenReturn(jwt);
98+
mockMvc.perform(post("/message")
99+
.content("Hello message")
100+
.header("Authorization", "Bearer " + jwt.getTokenValue()))
101+
.andExpect(status().isForbidden());
102+
}
103+
104+
@Test
105+
public void messageCanBeCreatedWithScopeMessageWriteAuthority()
106+
throws Exception {
107+
Jwt jwt = Jwt.withTokenValue("token")
108+
.header("alg", "none")
109+
.claim("scope", "message:write")
110+
.build();
111+
when(jwtDecoder.decode(anyString())).thenReturn(jwt);
112+
mockMvc.perform(post("/message")
113+
.content("Hello message")
114+
.header("Authorization", "Bearer " + jwt.getTokenValue()))
115+
.andExpect(status().isOk())
116+
.andExpect(content().string(is("Message was created. Content: Hello message")));
117+
}
72118
}

0 commit comments

Comments
 (0)