# 1. The four processes *Next: [2. Three ways to get a token for the next hop](02-three-ways-to-get-a-token.md)* Everything in this module runs against four real processes, because the questions it answers (“whose identity arrives?”, “what does the receiving service check?”) only have answers when there is a second process to arrive at. | Process | Port | What it is | |---|---|---| | `authserver` | 9000 | A real Spring Authorization Server. Mints every token used anywhere here | | `gateway` | 8080 | Spring Cloud Gateway Server MVC, proxying to `edge` | | `edge` | 8081 | Resource server **and** OAuth2 client. The middle hop | | `downstream` | 8082 | Resource server. Reports who it thinks is calling | | `mtls` | 8443 | Separate. Certificate authentication instead of tokens — chapter 6 | `./scripts/run.sh` starts the first four in order and waits for each. ## Getting a user token without a browser The "browser flow" is four HTTP requests and a cookie jar, and [`scripts/user-token.sh`](../scripts/user-token.sh) does all of it with `curl`: 1. `GET /oauth2/authorize?…` unauthenticated → the request is saved, 302 to `/login` 2. `GET /login`, scrape the `_csrf` hidden field 3. `POST /login` with the credentials and that token → 302 back to the saved request 4. `GET` the authorize URL again, now authenticated → 302 to the redirect URI with `?code=` 5. `POST /oauth2/token` with the code and the PKCE `code_verifier` [`docs/output/01-user-token.txt`](output/01-user-token.txt) is the token that comes out. Doing this once by hand is the fastest way to understand what an OIDC library is doing on your behalf. ## Four things that cost time while building this **`issuer-uri` creates a startup-ordering dependency.** Configuring an OAuth2 *client* with `spring.security.oauth2.client.provider..issuer-uri` makes `ClientRegistrations` fetch `/.well-known/openid-configuration` during context refresh. If the authorization server is not up, the client will not start: ``` ResourceAccessException: I/O error on GET request for "http://127.0.0.1:9000/.well-known/openid-configuration": Connection refused ``` Nothing in that message says "start order". Naming `token-uri` and `jwk-set-uri` explicitly removes the coupling, which is why `edge.yml` does. **`OAuth2AuthorizationServerConfiguration` no longer exists.** Every pre-7.0 Authorization Server tutorial opens with `OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http)`. That class, and the whole `org.springframework.security.oauth2.server.authorization.config.annotation.web.*` package tree, is **absent** from `spring-security-oauth2-authorization-server` 7.1.1. The configurer moved into `spring-security-config` at `org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization`, and there is now a DSL method: ```java http.oauth2AuthorizationServer(Customizer.withDefaults()) ``` It is a compile error, not a deprecation warning. **A public client is asked for consent.** `ClientAuthenticationMethod.NONE` plus `authorization_code` produced a `Consent required` page mid-flow, which stops any scripted redemption dead. `ClientSettings.builder().requireAuthorizationConsent(false)` is explicit in `AuthServerApplication` for that reason. **Spring Cloud is a different release train.** `spring-cloud-dependencies` 2025.1.3 — gateway 5.0.3 — declares `4.0.8` in `spring-cloud-build`. This module runs it under Boot **4.1.1** and it works, but that is a combination nobody tested, and it is the reason a Boot upgrade can be blocked by a gateway. Check `spring-cloud-build`'s POM before assuming the trains are aligned. --- *Next: [2. Three ways to get a token for the next hop](02-three-ways-to-get-a-token.md)*