[[_sso_with_oauth2_angular_js_and_spring_security_part_v]]
= Single Sign On with OAuth2

In this section we continue <<_the_api_gateway_pattern_angular_js_and_spring_security_part_iv,our discussion>> of how to use http://projects.spring.io/spring-security[Spring Security] with http://angular.io[Angular] in a "single page application". Here we show how to use http://projects.spring.io/spring-security-oauth/[Spring Security OAuth] together with http://projects.spring.io/spring-cloud/[Spring Cloud] to extend our API Gateway to do Single Sign On and OAuth2 token authentication to backend resources. This is the fifth in a series of sections, and you can catch up on the basic building blocks of the application or build it from scratch by reading the <<_spring_and_angular_js_a_secure_single_page_application,first section>>, or you can just go straight to the https://github.com/spring-guides/tut-spring-security-and-angular-js/tree/master/oauth2[source code in Github]. In the <<_the_api_gateway_pattern_angular_js_and_spring_security_part_iv,last section>> we built a small distributed application that used https://github.com/spring-projects/spring-session/[Spring Session] to authenticate the backend resources and http://projects.spring.io/spring-cloud/[Spring Cloud] to implement an embedded API Gateway in the UI server. In this section we extract the authentication responsibilities to a separate server to make our UI server the first of potentially many Single Sign On applications to the authorization server. This is a common pattern in many applications these days, both in the enterprise and in social startups. We will use an OAuth2 server as the authenticator, so that we can also use it to grant tokens for the backend resource server. Spring Cloud will automatically relay the access token to our backend, and enable us to further simplify the implementation of both the UI and resource servers.

____
Reminder: if you are working through this section with the sample application, be sure to clear your browser cache of cookies and HTTP Basic credentials. In Chrome the best way to do that for a single server is to open a new incognito window.
____

== Creating an OAuth2 Authorization Server

Our first step is to create a new server to handle authentication and token management. Following the steps in <<_spring_and_angular_js_a_secure_single_page_application,Part I>> we can begin with https://start.spring.io[Spring Boot Initializr]. E.g. using curl on a UN*X like system:

[source]
----
$ curl https://start.spring.io/starter.tgz -d style=web \
-d style=security -d name=authserver | tar -xzvf -
----

You can then import that project (it's a normal Maven Java project by default) into your favourite IDE, or just work with the files and "mvn" on the command line.

=== Adding the OAuth2 Dependencies

We need to add the http://projects.spring.io/spring-security-oauth[Spring OAuth] dependencies, so in our https://github.com/spring-guides/tut-spring-security-and-angular-js/blob/master/oauth2/authserver/pom.xml[POM] we add:

.pom.xml
[source,xml]
----
<dependency>
  <groupId>org.springframework.security.oauth</groupId>
  <artifactId>spring-security-oauth2</artifactId>
</dependency>
----

The authorization server is pretty easy to implement. A minimal version looks like this:

.AuthserverApplication.java
[source,java]
----
@SpringBootApplication
@EnableAuthorizationServer
public class AuthserverApplication extends WebMvcConfigurerAdapter {

  public static void main(String[] args) {
    SpringApplication.run(AuthserverApplication.class, args);
  }

}
----

We only have to do 1 more thing (after adding `@EnableAuthorizationServer`):

.application.properties
[source,properties]
---
...
security.oauth2.client.clientId: acme
security.oauth2.client.clientSecret: acmesecret
security.oauth2.client.authorized-grant-types: authorization_code,refresh_token,password
security.oauth2.client.scope: openid
---

This registers a client "acme" with a secret and some authorized grant types including "authorization_code".

Now let's get it running on port 9999, with a predictable password for testing:

.application.properties
[source,properties]
----
server.port=9999
security.user.password=password
server.contextPath=/uaa
...
----

We also set the context path so that it doesn't use the default ("/") because otherwise you can get cookies for other servers on localhost being sent to the wrong server. So get the server running and we can make sure it is working:

[source]
----
$ mvn spring-boot:run
----

or start the `main()` method in your IDE.

=== Testing the Authorization Server

Our server is using the Spring Boot default security settings, so like the server in <<_spring_and_angular_js_a_secure_single_page_application,Part I>> it will be protected by HTTP Basic authentication. To initiate an https://tools.ietf.org/html/rfc6749#section-1.3.1[authorization code token grant] you visit the authorization endpoint, e.g. at http://localhost:9999/uaa/oauth/authorize?response_type=code&client_id=acme&redirect_uri=http://example.com[http://localhost:9999/uaa/oauth/authorize?response_type=code&client_id=acme&redirect_uri=http://example.com] once you have authenticated you will get a redirect to example.com with an authorization code attached, e.g. http://example.com/?code=jYWioI[http://example.com/?code=jYWioI].

NOTE: for the purposes of this sample application we have created a client "acme" with no registered redirect, which is what enables us to get a redirect the example.com. In a production application you should always register a redirect (and use HTTPS).

The code can be exchanged for an access token using the "acme" client credentials on the token endpoint:

[source]
----
$ curl acme:acmesecret@localhost:9999/uaa/oauth/token  \
-d grant_type=authorization_code -d client_id=acme     \
-d redirect_uri=http://example.com -d code=jYWioI
{"access_token":"2219199c-966e-4466-8b7e-12bb9038c9bb","token_type":"bearer","refresh_token":"d193caf4-5643-4988-9a4a-1c03c9d657aa","expires_in":43199,"scope":"openid"}
----

The access token is a UUID ("2219199c…"), backed by an in-memory token store in the server. We also got a refresh token that we can use to get a new access token when the current one expires.

NOTE: since we allowed "password" grants for the "acme" client we can also get a token directly from the token endpoint using curl and user credentials instead of an authorization code. This is not suitable for a browser based client, but it's useful for testing.

If you followed the link above you would have seen the whitelabel UI provided by Spring OAuth. To start with we will use this and we can come back later to beef it up like we did in <<_the_login_page_angular_js_and_spring_security_part_ii,Part II>> for the self-contained server.

[[changing-the-resource-server]]
== Changing the Resource Server

If we follow on from <<_the_api_gateway_pattern_angular_js_and_spring_security_part_iv,Part IV>>, our resource server is using https://github.com/spring-projects/spring-session/[Spring Session] for authentication, so we can take that out and replace it with Spring OAuth. We also need to remove the Spring Session and Redis dependencies, so replace this:

.pom.xml
[source,xml]
----
<dependency>
  <groupId>org.springframework.session</groupId>
  <artifactId>spring-session</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-redis</artifactId>
</dependency>
----

with this:

.pom.xml
[source,xml]
----
<dependency>
  <groupId>org.springframework.security.oauth</groupId>
  <artifactId>spring-security-oauth2</artifactId>
</dependency>
----

and then remove the session `Filter` from the https://github.com/spring-guides/tut-spring-security-and-angular-js/blob/master/vanilla-oauth2/resource/src/main/java/demo/ResourceApplication.java[main application class], replacing it with the convenient `@EnableResourceServer` annotation (from Spring Security OAuth2):

.ResourceApplication.java
[source,java]
----
@SpringBootApplication
@RestController
@EnableResourceServer
class ResourceApplication {

  @RequestMapping("/")
  public Message home() {
    return new Message("Hello World");
  }

  public static void main(String[] args) {
    SpringApplication.run(ResourceApplication.class, args);
  }
}

----

With that one change the app is ready to challenge for an access token instead of HTTP Basic, but we need a config change to actually finish the process. We are going to add a small amount of external configuration (in "application.properties") to allow the resource server to decode the tokens it is given and authenticate a user:

.application.properties
[source,properties]
----
...
security.oauth2.resource.userInfoUri: http://localhost:9999/uaa/user
----

This tells the server that it can use the token to access a "/user" endpoint and use that to derive authentication information (it's a bit like the https://developers.facebook.com/docs/graph-api/reference/v2.2/user/?locale=en_GB["/me" endpoint] in the Facebook API). Effectively it provides a way for the resource server to decode the token, as expressed by the `ResourceServerTokenServices` interface in Spring OAuth2.

Run the application and hit the home page with a command line client:

[source]
----
$ curl -v localhost:9000
> GET / HTTP/1.1
> User-Agent: curl/7.35.0
> Host: localhost:9000
> Accept: */*
>
< HTTP/1.1 401 Unauthorized
...
< WWW-Authenticate: Bearer realm="null", error="unauthorized", error_description="An Authentication object was not found in the SecurityContext"
< Content-Type: application/json;charset=UTF-8
{"error":"unauthorized","error_description":"An Authentication object was not found in the SecurityContext"}
----

and you will see a 401 with a "WWW-Authenticate" header indicating that it wants a bearer token.

NOTE: the `userInfoUri` is by far not the only way of hooking a resource server up with a way to decode tokens. In fact it's sort of a lowest common denominator (and not part of the spec), but quite often available from OAuth2 providers (like Facebook, Cloud Foundry, Github), and other choices are available. For instance you can encode the user authentication in the token itself (e.g. with http://jwt.io/[JWT]), or use a shared backend store. There is also a `/token_info` endpoint in CloudFoundry, which provides more detailed information than the user info endpoint, but which requires more thorough authentication. Different options (naturally) provide different benefits and trade-offs, but a full discussion of those is outside the scope of this section.

== Implementing the User Endpoint

On the authorization server we can easily add that endpoint

.AuthserverApplication.java
[source,java]
----
@SpringBootApplication
@RestController
@EnableAuthorizationServer
@EnableResourceServer
public class AuthserverApplication {

  @RequestMapping("/user")
  public Principal user(Principal user) {
    return user;
  }

  ...

}
----

We added a `@RequestMapping` the same as the UI server in <<_the_login_page_angular_js_and_spring_security_part_ii,Part II>>, and also the `@EnableResourceServer` annotation from Spring OAuth, which by default secures everything in an authorization server except the "/oauth/*" endpoints.

With that endpoint in place we can test it and the greeting resource, since they both now accept bearer tokens that were created by the authorization server:

[source]
----
$ TOKEN=2219199c-966e-4466-8b7e-12bb9038c9bb
$ curl -H "Authorization: Bearer $TOKEN" localhost:9000
{"id":"03af8be3-2fc3-4d75-acf7-c484d9cf32b1","content":"Hello World"}
$ curl -H "Authorization: Bearer $TOKEN" localhost:9999/uaa/user
{"details":...,"principal":{"username":"user",...},"name":"user"}
----

(substitute the value of the access token that you obtain from your own authorization server to get that working yourself).

== The UI Server

The final piece of this application we need to complete is the UI server, extracting the authentication part and delegating to the authorization server. So, as with link:#changing-the-resource-server[the resource server], we first need to remove the Spring Session and Redis dependencies and replace them with Spring OAuth2. Because we are using Zuul in the UI layer we actually use `spring-cloud-starter-oauth2` instead of `spring-security-oauth2` directly (this sets up some autoconfiguration for relaying tokens through the proxy).

Once that is done we can remove the session filter and the "/user" endpoint as well, and set up the application to redirect to the authorization server (using the `@EnableOAuth2Sso` annotation):

.UiApplication.java
[source,java]
----
@SpringBootApplication
@EnableZuulProxy
@EnableOAuth2Sso
public class UiApplication {

  public static void main(String[] args) {
    SpringApplication.run(UiApplication.class, args);
  }

...

}
----

Recall from <<_the_api_gateway_pattern_angular_js_and_spring_security_part_iv,Part IV>> that the UI server, by virtue of the `@EnableZuulProxy`, acts an API Gateway and we can declare the route mappings in YAML. So the "/user" endpoint can be proxied to the authorization server:

.application.yml
[source,yaml]
----
zuul:
  routes:
    resource:
      path: /resource/**
      url: http://localhost:9000
    user:
      path: /user/**
      url: http://localhost:9999/uaa/user
----

Lastly, we need to change the application to a `WebSecurityConfigurerAdapter` since now it is going to be used to modify the defaults in the SSO filter chain set up by `@EnableOAuth2Sso`:

.SecurityConfiguration.java
[source,java,indent=0]
----
@SpringBootApplication
@EnableZuulProxy
@EnableOAuth2Sso
public class UiApplication extends WebSecurityConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
      http
          .logout().logoutSuccessUrl("/").and()
          .authorizeRequests().antMatchers("/index.html", "/app.html", "/")
          .permitAll().anyRequest().authenticated().and()
          .csrf()
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
    }

}
----

The main changes (apart from the base class name) are that the matchers
go into their own method, and there is no need for `formLogin()` any more.
The explicit `logout()` configuration explicitly adds a success url that
is unprotected, so that an XHR request to `/logout` will return successfully.

There are also some mandatory external configuration properties for the
`@EnableOAuth2Sso` annotation to be able to contact and authenticate with
the right authorization server. So we need this in `application.yml`:

.application.yml
[source,yaml]
----
security:
  ...
  oauth2:
    client:
      accessTokenUri: http://localhost:9999/uaa/oauth/token
      userAuthorizationUri: http://localhost:9999/uaa/oauth/authorize
      clientId: acme
      clientSecret: acmesecret
    resource:
      userInfoUri: http://localhost:9999/uaa/user
----

The bulk of that is about the OAuth2 client ("acme") and the
authorization server locations. There is also a `userInfoUri` (just
like in the resource server) so that the user can be authenticated in
the UI app itself.

NOTE: If you want the UI application be able to refresh expired
access tokens automatically, you have to get an `OAuth2RestOperations`
injected into the Zuul filter that does the relay. You can do this
by just creating a bean of that type (check the `OAuth2TokenRelayFilter`
for details):
[source,java]
----
@Bean
protected OAuth2RestTemplate OAuth2RestTemplate(
    OAuth2ProtectedResourceDetails resource, OAuth2ClientContext context) {
  return new OAuth2RestTemplate(resource, context);
}
----

=== In the Client

There are some tweaks to the UI application on the front end that we still need to make to trigger the redirect to the authorization server. In this simple demo we can strip the Angular app down to its bare essentials so you can see what is going on more clearly. So we forgo, for now, the use of forms or routes, and we go back to a single Angular component:

.app.component.ts
[source,javascript]
----
include::ui/src/app/app.component.ts[indent=0]
----

The `AppComponent` handles everything, fetching the user details and, if successful, the greeting. It also provides the `logout` function.

Now we need to create the template for this new component:

app.component.html
[source,html]
----
include::ui/src/app/app.component.html[indent=0]
----

and include it in the home page as `<app-root/>`.

Note that the navigation link for "Login" is a regular link with an `href` (not an Angular route). The "/login" endpoint that this goes to is handled by Spring Security and if the user is not authenticated it will result in a redirect to the authorization server.

== How Does it Work?

Run all the servers together now, and visit the UI in a browser at http://localhost:8080[http://localhost:8080]. Click on the "login" link and you will be redirected to the authorization server to authenticate (HTTP Basic popup) and approve the token grant (whitelabel HTML), before being redirected to the home page in the UI with the greeting fetched from the OAuth2 resource server using the same token as we authenticated the UI with.

The interactions between the browser and the backend can be seen in your browser if you use some developer tools (usually F12 opens this up, works in Chrome by default, may require a plugin in Firefox). Here's a summary:

|===
|Verb |Path |Status |Response

|GET |/ |200 |index.html
|GET |/*.js |200 |Assets from angular
|GET |/user |302 |Redirect to login page
|GET |/login |302 |Redirect to auth server
|GET |(uaa)/oauth/authorize |401 |(ignored)
|GET |/login |302 |Redirect to auth server
|GET |(uaa)/oauth/authorize |200 |HTTP Basic auth happens here
|POST |(uaa)/oauth/authorize |302 |User approves grant, redirect to /login
|GET |/login |302 |Redirect to home page
|GET |/user |200 |(Proxied) JSON authenticated user
|GET |/app.html |200 |HTML partial for home page
|GET |/resource |200 |(Proxied) JSON greeting
|===

The requests prefixed with (uaa) are to the authorization server. The responses that are marked "ignored" are responses received by Angular in an XHR call, and since we aren't processing that data they are dropped on the floor. We do look for an authenticated user in the case of the "/user" resource, but since it isn't there in the first call, that response is dropped.

In the "/trace" endpoint of the UI (scroll down to the bottom) you will see the proxied backend requests to "/user" and "/resource", with `remote:true` and the bearer token instead of the cookie (as it would have been in <<_the_api_gateway_pattern_angular_js_and_spring_security_part_iv,Part IV>>) being used for authentication. Spring Cloud Security has taken care of this for us: by recognising that we has `@EnableOAuth2Sso` and `@EnableZuulProxy` it has figured out that (by default) we want to relay the token to the proxied backends.

NOTE: As in previous sections, try to use a different browser for "/trace" so that there is no chance of authentication crossover (e.g. use Firefox if you used Chrome for testing the UI).

== The Logout Experience

If you click on the "logout" link you will see that the home page changes (the greeting is no longer displayed) so the user is no longer authenticated with the UI server. Click back on "login" though and you actually _don't_ need to go back through the authentication and approval cycle in the authorization server (because you haven't logged out of that). Opinions will be divided as to whether that is a desirable user experience, and it's a notoriously tricky problem (Single Sign Out: http://www.sciencedirect.com/science/article/pii/S2214212614000179[Science Direct article] and https://wiki.shibboleth.net/confluence/display/SHIB2/SLOIssues[Shibboleth docs]). The ideal user experience might not be technically feasible, and you also have to be suspicious sometimes that users really want what they say they want. "I want 'logout' to log me out" sounds simple enough, but the obvious response is, "Logged out of what? Do you want to be logged out of _all_ the systems controlled by this SSO server, or just the one that you clicked the 'logout' link in?" If you are interested then there is <<_oauth2_logout_angular_js_and_spring_security_part_ix,a later section>> of this tutorial where it is discussed in more depth.

== Conclusion

This is almost the end of our shallow tour through the Spring Security and Angular stack. We have a nice architecture now with clear responsibilities in three separate components, UI/API Gateway, resource server and authorization server/token granter. The amount of non-business code in all layers is now minimal, and it's easy to see where to extend and improve the implementation with more business logic. The next steps will be to tidy up the UI in our authorization server, and probably add some more tests, including tests on the JavaScript client. Another interesting task is to extract all the boiler plate code and put it in a library (e.g. "spring-security-angular") containing Spring Security and Spring Session autoconfiguration and some webjars resources for the navigation controller in the Angular piece. Having read the sections in thir series, anyone who was hoping to learn the inner workings of either Angular or Spring Security will probably be disappointed, but if you wanted to see how they can work well together and how a little bit of configuration can go a long way, then hopefully you will have had a good experience. http://projects.spring.io/spring-cloud/[Spring Cloud] is new and these samples required snapshots when they were written, but there are release candidates available and a GA release coming soon, so check it out and send some feedback https://github.com/spring-cloud[via Github] or https://gitter.im/spring-cloud/spring-cloud[gitter.im].

The <<_multiple_ui_applications_and_a_gateway_single_page_application_with_spring_and_angular_js_part_vi,next section>> in the series is about access decisions (beyond authentication) and employs multiple UI applications behind the same proxy.

== Addendum: Bootstrap UI and JWT Tokens for the Authorization Server

You will find another version of this application in the https://github.com/spring-guides/tut-spring-security-and-angular-js/tree/master/oauth2[source code in Github] which has a pretty login page and user approval page implemented similarly to the way we did the login page in <<_the_login_page_angular_js_and_spring_security_part_ii,Part II>>. It also uses http://jwt.io/[JWT] to encode the tokens, so instead of using the "/user" endpoint, the resource server can pull enough information out of the token itself to do a simple authentication. The browser client still uses it, proxied through the UI server, so that it can determine if a user is authenticated (it doesn't need to do that very often, compared to the likely number of calls to a resource server in a real application).
