Skip to content

Latest commit

 

History

History
404 lines (327 loc) · 18 KB

CUSTOMIZATION.md

File metadata and controls

404 lines (327 loc) · 18 KB

Customization

This document describes how to customize this authorization server implementation.

Overview

This authorization server implementation uses Authlete as its backend. What this means are (1) that the core part of the implementation of OAuth 2.0 and OpenID Connect is not in the source tree of spring-oauth-server but in the Authlete server on cloud, and (2) that authorization data such as access tokens, settings of the authorization server itself and settings of client applications are not stored in any local database but in the database on cloud. Therefore, to put it very simply, this implementation is just an intermediary between client applications and Authlete server as illustrated below.

+--------+          +---------------------+          +----------+
|        |          |                     |          |          |
| Client | <------> | spring-oauth-server | <------> | Authlete |
|        |          |                     |          |          |
+--------+          +---------------------+          +----------+

However, because Authlete focuses on authorization and does NOT do anything about end-user authentication, functions related to authentication are implemented in the source tree of spring-oauth-server.

Therefore, at least, you must customize parts related to end-user authentication. On the other hand, customization of other parts such as UI design of the authorization page is optional.

Overall Structure

Authlete provides Web APIs that can be used to write an authorization server. authlete-java-common is a library which directly communicates with the Web APIs, and authlete-java-jaxrs is a library which provides utility classes wrapping the authlete-java-common API to make it much easier for developers to implement an authorization server than using authlete-java-common API directly. spring-oauth-server is written using Spring Framework and authlete-java-jaxrs API exposed by the utility classes.

As its name implies, authlete-java-jaxrs library depends on JAX-RS 2.0 API. JAX-RS means The Java API for RESTful Web Services. JAX-RS 2.0 API has been standardized by JSR 339 and it is included in Java EE 7.

The figure below illustrates the relationship among the components mentioned so far.

+----------------------------------------+
|          spring-oauth-server           |
+--------+----+--------------------------+
|        |    |     authlete-java-jaxrs  |
| Spring |    +---+----------------------+          +----------+
|        | JAX-RS | authlete-java-common | <------> | Authlete |
+--------+-------------------------------+          +----------+

Authorization Endpoint

The implementation of the authorization endpoint is in AuthorizationEndpoint.java. The code is incredibly short although it supports OpenID Connect in addition to OAuth 2.0. There is little need to change this file.

The implementation uses AuthorizationRequestHandler class and delegates the task to handle an authorization request to handle() method of the class. Details about the class is written in the README file of authlete-java-jaxrs library. What is important here is that the constructor of the class requires an implementation of AuthorizationRequestHandlerSpi interface and that the implementation must be provided by you. In other words, the methods in AuthorizationRequestHandlerSpi interface are customization points.

The interface has the methods listed below. See the JavaDoc of authlete-java-jaxrs API for details about the requirements of these methods.

  1. boolean isUserAuthenticated()
  2. long getUserAuthenticatedAt()
  3. String getUserSubject()
  4. String getAcr()
  5. Response generateAuthorizationPage(AuthorizationResponse)

The most important method among the above is generateAuthorizationPage(). The method is called to generate an authorization page. In contrast, the other methods are not so important because they are called only when an authorization request comes with a special request parameter prompt=none. If you have no mind to support prompt=none, you can leave your implementations of the methods empty. Details about prompt=none is written in "3.1.2.1. Authorization Request" of OpenID Connect Core 1.0.

The implementation of AuthorizationRequestHandlerSpi interface in spring-oauth-server is written in AuthorizationRequestHandlerSpiImpl.java. The implementation class in the file, AuthorizationRequestHandlerSpiImpl, extends AuthorizationRequestHandlerSpiAdapter class which is an empty implementation of AuthorizationRequestHandlerSpi interface, and overrides generateAuthorizationPage() method only. The code snippet below shows the rough structure of the implementation.

class AuthorizationRequestHandlerSpiImpl extends AuthorizationRequestHandlerSpiAdapter
{
    ......

    @Override
    public Response generateAuthorizationPage(AuthorizationResponse info)
    {
        ......
    }
}

Authorization Page

As mentioned, generateAuthorizationPage() in AuthorizationRequestHandlerSpi interface is a method to generate an authorization page. The current implementation of the method in spring-oauth-server retrieves data from the argument (an intance of AuthorizationResponse class which represents a response from Authlete's /api/auth/authorization API) and embeds them into an HTML template, authorization.ftl. To achieve this, the implementation uses Viewable class.

If you want to customize the authorization page, change the implementation of generateAuthorizationPage() method and/or the template of the authorization page (authorization.ftl). See the JavaDoc of authlete-java-common library for details about AtuhorizationResponse class.

Internationalization

For the internationalization of the authorization page, you may take ui_locales parameter into consideration which may be contained in an authorization request. It is a new request parameter defined in OpenID Connect Core 1.0. The following is the description about the parameter excerpted from the specification.

OPTIONAL. End-User's preferred languages and scripts for the user interface, represented as a space-separated list of BCP47 [RFC5646] language tag values, ordered by preference. For instance, the value "fr-CA fr en" represents a preference for French as spoken in Canada, then French (without a region designation), followed by English (without a region designation). An error SHOULD NOT result if some or all of the requested locales are not supported by the OpenID Provider.

You can get the value of ui_locales request paremeter as a String array by calling getUiLocales() method of AuthorizationResponse instance. Note that, however, you have to explicitly specify which UI locales to support using the management console (Service Owner Console) because getUiLocales() method returns only supported UI locales. In other words, it is ensured that the array returned by getUiLocales() never contains unsupported UI locales whatever ui_locales request parameter contains.

It is up to you whether to honor ui_locales parameter or not. Of course, you may use any means you like to internationalize the authorization page.

Display type

An authorization request may contain display request parameter to specify how to display the authorization page. It is a new request parameter defined in OpenID Connect Core 1.0. The predefined values of the request parameter are as follows. The descriptions in the table are excerpts from the specification.

Value Description
page The Authorization Server SHOULD display the authentication and consent UI consistent with a full User Agent page view. If the display parameter is not specified, this is the default display mode.
popup The Authorization Server SHOULD display the authentication and consent UI consistent with a popup User Agent window. The popup User Agent window should be of an appropriate size for a login-focused dialog and should not obscure the entire window that it is popping up over.
touch The Authorization Server SHOULD display the authentication and consent UI consistent with a device that leverages a touch interface.
wap The Authorization Server SHOULD display the authentication and consent UI consistent with a "feature phone" type display.

You can get the value of display request parameter as an instance of Display enum by calling getDisplay() method of AuthorizationResponse instance. By default, all the display types are checked as supported in the management console (Service Owner Console), but you can uncheck them to declare some values are not supported. If an unsupported value is specified as the value of display request parameter, it will result in returning an invalid_request error to the client application that made the authorization request.

Authorization Decision Endpoint

In an authorization page, an end-user decides either to grant permissions to the client application which made the authorization request or to deny the authorization request. An authorization server must be able to receive the decision and return a proper response to the client application according to the decision.

The current implementation of spring-oauth-server receives the end-user's decision at /api/authorization/decision. In this document, we call the endpoint authorization decision endpoint. In spring-oauth-server, the implementation of the authorization decision endpoint is in AuthorizationDecisionEndpoint.java.

The implementation uses AuthorizationDecisionHandler class and delegates the task to handle an end-user's decision to handle() method of the class. Details about the class is written in the README file of authlete-java-jaxrs library. What is important here is that the constructor of the class requires an implementation of AuthorizationDecisionHandlerSpi interface and that the implementation must be provided by you. In other words, the methods in AuthorizationDecisionHandlerSpi interface are customization points.

The interface has the methods listed below. See the JavaDoc of authlete-java-jaxrs API for details about the requirements of these methods.

  1. boolean isClientAuthorized()
  2. long getUserAuthenticatedAt()
  3. String getUserSubject()
  4. String getAcr()
  5. getUserClaim(String claimName, String languageTag)

The implementation of AuthorizationDecisionHandlerSpi interface in spring-oauth-server is written in AuthorizationDecisionHandlerSpiImpl.java. The implementation class in the file, AuthorizationDecisionHandlerSpiImpl, extends AuthorizationDecisionHandlerSpiAdapter class which is an empty implementation of AuthorizationDecisionHandlerSpi interface, and overrides all the methods except getAcr(). The code snippet below shows the rough structure of the implementation.

class AuthorizationDecisionHandlerSpiImpl extends AuthorizationDecisionHandlerSpiAdapter
{
    ......

    @Override
    public boolean isClientAuthorized()
    {
        ......
    }

    @Override
    public long getUserAuthenticatedAt()
    {
        ......
    }

    @Override
    public String getUserSubject()
    {
        ......
    }

    @Override
    public Object getUserClaim(String claimName, String languageTag)
    {
        ......
    }
}

End-User Authentication

Authlete does not care about how to authenticate an end-user at all. Instead, Authlete requires the subject of the authenticated end-user.

Subject is a technical term in the area related to identity and it means a unique identifier. In a typical case, subjects of end-users are values of the primary key column or another unique column in a user database.

When an end-user grants permissions to a client application, you have to let Authlete know the subject of the end-user. In the context of AuthorizationDecisionHandlerSpi interface, this can be described as follows: "if isClientAuthorized() returns true, then getUserSubject() must return the subject of the end-user."

For end-user authentication, spring-oauth-server has UserDao class and UserEntity class. These two classes compose a dummy user database. Of course, you have to replace them with your own implementation to refer to your actual user database.

Token Endpoint

The implementation of the token endpoint is in TokenEndpoint.java. The code is incredibly short and there is little need to change the content of the file.

The implementation uses TokenRequestHandler class and delegates the task to handle a token request to handle() method of the class. Details about the class is written in the README file of authlete-java-jaxrs library. What is important here is that the constructor of the class requires an implementation of TokenRequestHandlerSpi interface and that the implementation must be provided by you. In other words, the methods in TokenRequestHandlerSpi interface are customization points.

The current definition of the interface has only one method named authenticateUser. This method is used to authenticate an end-user. However, the method is called only when the grant type of a token request is Resource Owner Password Credentials. Therefore, if you have no mind to support the grant type, you can leave your implementation of the method empty.

The implementation of TokenRequestHandlerSpi interface in spring-oauth-server is written in TokenRequestHandlerSpiImpl.java. The implmentation class in the file, TokenRequestHandlerSpiImpl, extends TokenRequestHandlerSpiAdapter class which is an empty implementation of TokenRequestHandlerSpi interface, and overrides authenticateUser() method. The code snippet below shows the rough structure of the implementation.

class TokenRequestHandlerSpiImpl extends TokenRequestHandlerSpiAdapter
{
    ......

    @Override
    public String authenticateUser(String username, String password)
    {
        ......
    }
}

Introspection Endpoint

The implementation of the introspection endpoint is in IntrospectionEndpoint.java.

RFC 7662 (OAuth 2.0 Token Introspection) requires that the endpoint be protected in some way or other. The implementation of the protection in IntrospectionEndpoint.java is for demonstration purpose only, and it is not suitable for commercial use. Therefore, modify the code accordingly.

See Also

Contact

Purpose Email Address
General [email protected]
Sales [email protected]
PR [email protected]
Technical [email protected]