README.adoc 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. = OAuth 2.0 Authorization Server Sample
  2. This sample demonstrates Authorization Server with the `client_credentials` grant type. This authorization server is configured to generate JWT tokens signed with the `RS256` algorithm.
  3. * <<running-the-tests, Running the tests>>
  4. * <<running-the-app, Running the app>>
  5. * <<testing-with-a-resource-server, Testing with a resource server>>
  6. [[running-the-tests]]
  7. == Running the tests
  8. To run the tests, do:
  9. ```bash
  10. ./gradlew integrationTest
  11. ```
  12. Or import the project into your IDE and run `OAuth2AuthorizationServerApplicationTests` from there.
  13. === What is it doing?
  14. The tests are making requests to the token endpoint with the `client_credentials` grant type using the `client_secret_basic` authentication method, and subsequently verifying them using the token introspection endpoint.
  15. The introspection endpoint response is used to verify the token (decode the JWT in this case), returning the payload including the requested scope:
  16. ```json
  17. {
  18. "active": true,
  19. "aud": [
  20. "messaging-client"
  21. ],
  22. "client_id": "messaging-client",
  23. "exp": 1627070941,
  24. "iat": 1627070641,
  25. "iss": "http://localhost:9000",
  26. "jti": "987599e3-1048-4fe8-89df-ad113aef2d6c",
  27. "nbf": 1627070641,
  28. "scope": "message:read",
  29. "sub": "messaging-client",
  30. "token_type": "Bearer"
  31. }
  32. ```
  33. Note that Spring Security does not require the token introspection endpoint when configured to use the Bearer scheme with JWTs, this is simply used for demonstration purposes.
  34. [[running-the-app]]
  35. == Running the app
  36. To run as a stand-alone application, do:
  37. ```bash
  38. ./gradlew bootRun
  39. ```
  40. Or import the project into your IDE and run `OAuth2AuthorizationServerApplication` from there.
  41. Once it is up and running, you can issue the following request:
  42. ```bash
  43. curl -X POST messaging-client:secret@localhost:9000/oauth2/token -d "grant_type=client_credentials" -d "scope=message:read"
  44. ```
  45. This returns something like the following:
  46. ```json
  47. {
  48. "access_token": "eyJraWQiOiI4YWY4Zjc2Zi0zMTdkLTQxZmYtYWY5Yi1hZjg5NDg4ODM5YzciLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJtZXNzYWdpbmctY2xpZW50IiwiYXVkIjoibWVzc2FnaW5nLWNsaWVudCIsIm5iZiI6MTYyNzMzNDQ1MCwic2NvcGUiOlsibWVzc2FnZTpyZWFkIl0sImlzcyI6Imh0dHA6XC9cL2xvY2FsaG9zdDo5MDAwIiwiZXhwIjoxNjI3MzM0NzUwLCJpYXQiOjE2MjczMzQ0NTAsImp0aSI6IjBiYjYwZjhkLWIzNjItNDk0MC05MGRmLWZhZDg4N2Q1Yzg1ZSJ9.O8dI67B_feRjOn6pJi5ctPJmUJCNpV77SC4OiWqmpa5UHvf4Ud6L6EFe9LKuPIRrEWi8rMdCdMBOPKQMXvxLoI3LMUPf7Yj973uvZN0E988MsKwhGwxyaa_Wam8wFlk8aQlN8SbW3cKdeH-nKloNMdwjfspovefX521mxouaMjmyXdIFrM5WZ15GZK69NIniACSatE-pc9TAjKYBDbC65jVt_zHEvDQbEkZulF2bjrGOZC8C3IbJWnlKgkcshrY44TtrGPyCp2gIS0TSUUsG00iSBBC8E8zPU-YdfaP8gB9_FwUwK9zfy_hU2Ykf2aU3eulpGDVLn2rCwFeK86Rw1w",
  49. "expires_in": 299,
  50. "scope": "message:read",
  51. "token_type": "Bearer"
  52. }
  53. ```
  54. In order to make the same token introspection request as the tests, export the access token from the response:
  55. ```bash
  56. export TOKEN=...
  57. ```
  58. Then issue the following request:
  59. ```bash
  60. curl -X POST messaging-client:secret@localhost:9000/oauth2/introspect -d "token=$TOKEN"
  61. ```
  62. Which will return something like the following:
  63. ```json
  64. {
  65. "active": true,
  66. "aud": [
  67. "messaging-client"
  68. ],
  69. "client_id": "messaging-client",
  70. "exp": 1627334750,
  71. "iat": 1627334450,
  72. "iss": "http://localhost:9000",
  73. "jti": "0bb60f8d-b362-4940-90df-fad887d5c85e",
  74. "nbf": 1627334450,
  75. "scope": "message:read",
  76. "sub": "messaging-client",
  77. "token_type": "Bearer"
  78. }
  79. ```
  80. [[testing-with-a-resource-server]]
  81. == Testing with a resource server
  82. This sample can be used in conjunction with a resource server, such as the https://github.com/spring-projects/spring-security-samples/tree/main/servlet/spring-boot/java/oauth2/resource-server/hello-security[resource-server sample] in this project.
  83. To change the sample to point to this authorization server, simply find this property in that project's `application.yml`:
  84. ```yaml
  85. spring:
  86. security:
  87. oauth2:
  88. resourceserver:
  89. jwt:
  90. jwk-set-uri: ${mockwebserver.url}/.well-known/jwks.json
  91. ```
  92. And change the property to:
  93. ```yaml
  94. spring:
  95. security:
  96. oauth2:
  97. resourceserver:
  98. jwt:
  99. jwk-set-uri: http://localhost:9000/oauth2/jwks
  100. ```
  101. And then you can run that app similarly to the authorization server:
  102. ```bash
  103. ./gradlew bootRun
  104. ```
  105. Once it is up and running, you can issue the following request:
  106. ```bash
  107. curl -X POST messaging-client:secret@localhost:9000/oauth2/token -d "grant_type=client_credentials" -d "scope=message:read"
  108. ```
  109. Then, export the access token from the response:
  110. ```bash
  111. export TOKEN=...
  112. ```
  113. Then issue the following request:
  114. ```bash
  115. curl -H "Authorization: Bearer $TOKEN" localhost:8080
  116. ```
  117. Which will respond with the phrase:
  118. ```
  119. Hello, messaging-client!
  120. ```