ASAP Authentication - Java

A library that creates and verifies JSON Web Tokens (JWT) for service to service authentication purposes using the Atlassian Service Authentication Protocol (ASAP).

Atlassian S2S Authentication Protocol (ASAP) - Specification

Bamboo build plan (only for releases, branch builds use Pipelines)

JIRA project

Making arbitrary curl requests from the command line

scripts/jwtexec.groovy is a portable Groovy script which lets you easily generate JWT Authorization headers. You can copy just this single file to any server. It will fetch its dependencies at runtime.

The script has builtin help, so run it and see! Here's one simple example:

groovy -Djwt.audience=resource-server -Djwt.issuer=client jwtexec.groovy curl -X POST http://localhost:8080/resource

Development Requirements

  • Java 1.8
  • mvn 3.x

Setting up a development environment

  1. Clone the repository
  2. mvn clean verify to build and run tests (unit and integration)

Running the Server

First install the libraries: mvn install.

If you want to run a development server, use mvn -Pserver -pl examples -nsu and point your client to http://localhost:8080/

To customize the audience and/or base url property of the resource server:

mvn -Pserver -Dasap.resource.server.audience=my-resource-server \
             -Dasap.public.key.repo.url= \
             -Dasap.resource.server.authorized.subjects=issuer1,issuer2,issuer3 \
             -pl examples -nsu

If you want to debug the server

export MAVEN_OPTS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=5005,server=y,suspend=n"

* The default audience, port and other configuration for the test server are configured

Running the Client

First install the libraries: mvn install.

If you want to run a simple client for development, use mvn -Pclient -pl examples -nsu

To customize the client properties, set the relevant system properties

mvn -Pclient -Dasap.client.issuer=issuer1 \
             -Dasap.client.keyId=issuer1/apikey \
             -Dasap.client.audience=my-resource-server \
             -Dasap.client.privateKey=file:///Path/To/Private/Key/ \
             -Dasap.client.resource.server.url=http://localhost:8080 \
             -pl examples -nsu

In the above example, the private key is expected to be located at /Path/To/Private/Key/myclient/apikey

For client authentication to be successful with a resource server, the corresponding public key must exist in the key
repository under myclient/apikey

Generating key pairs

For your convenience, there is a simple utility called KeyGen in the test folder. Run it
to generate a pair of RSA keys and a pair of EC keys. RSA keys are to be used with the RSxxx
and PSxxx families of JWA Algorithms. EC keys are to be used with the ECxxx familiy of JWA
Algorithms. The keys are written as PEM files in the current directory.

Alternatively, you can use OpenSSL from the command line to generate the key pairs:

# Generate private key
$ openssl genrsa -out private.pem 2048

# Generate corresponding public key
$ openssl rsa -in private.pem -outform PEM -pubout -out public.pem


If you want to run a sample benchmark, use mvn -Pbenchmark

To customize the benchmark properties (e.g. to use a differnt algorithm or key) please override the
system properties accordingly.


Follow Semantic Versioning (SemVer) in pom.xml for project artifacts.

To release, run the manual "Release" stage on the Bamboo build plan for your build.


Maven dependencies

The library is split in many modules. Most applications will require asap-common and at least one of the client or server modules. For instance, to add the dependency on asap-common using Maven, add the following to the pom.xml of your project:


Replace ${asap.version} with the most recent version of this library.

Find the latest released version of the library at:


  • Clients can generate a HTTP Authorization header using the class AuthorizationHeaderGenerator
  • Clients using Jersey can use AsapAuthenticationFilter client filter
  • Clients using Spring MVC can use AsapInterceptor client request interceptor

Server resource authentication using Jersey

note that the implementation will return 401 for an authentication failure and 403 for an authorisation failure
1. Teach Jersey about the JwtAuth annotation by adding com.atlassian.asap.core.server.jersey to your Jersey packages configuration. In your web.xml this will look like:

  1. Annotate your Jersey resources to require authentication:

    public String getMyResource(
        @JwtAuth(authorizedSubjects={"alice", "bob"}) Jwt jwt
        // `jwt` is guaranteed to be non-null

Server resource authentication using Spring MVC

note that the implementation will return 401 for an authentication failure and 403 for an authorisation failure
1. Add the AuthorizationInterceptor and RequestAuthenticationFilterBean into your spring configuration. This will look like:

    public class MyConfiguration implements WebMvcConfigurer {

    private AuthorizationInterceptor authorizationInterceptor;

    public AsapValidator asapValidator(AsapServerProperties asapServerProperties) {
        return AsapValidator.newAnnotationWithConfigValidator(
            new HashSet<>(asapServerProperties.getAuthorizedSubjects()),
            new HashSet<>(asapServerProperties.getAuthorizedIssuers()));

    public AuthorizationInterceptor authorizationInterceptor(AsapValidator asapValidator) {
        return new AuthorizationInterceptor(asapValidator);

    public Filter requestAuthenticationFilter(RequestAuthenticator requestAuthenticator) {
        boolean allowAnonymousRequests = true;
        return new RequestAuthenticationFilterBean(requestAuthenticator, allowAnonymousRequests);

    public void addInterceptors(InterceptorRegistry registry) {
            .order(Ordered.LOWEST_PRECEDENCE); //lowest precedence so that other things like zipkin get a chance to run
  1. Annotate your Spring Controllers to require authentication:

    @Asap(authorizedSubjects={"alice", "bob"})
    public String getMyResource()
       return "some resource";

Server resource authentication with a servlet filter

Resource Servers may implement authentication of incoming client requests using RequestAuthenticationFilterBean.

Options for configuring the servlet filter:

  1. Spring configuration. See the javadoc for the RequestAuthenticationFilterBean default constructor for more details.
  2. Manual configuration by calling static createDefault method with the necessary parameters.

Server authentication/authorization using Spring Security

Use the asap-server-spring-security artifact. See the integration tests and the Javadoc of AsapAuthenticationProvider.

The service API

Alternative, the asap-service-api and its implementation in asap-service-core may be used to configure the application's
client and server configuration globally. This is likely to be a good option for larger applications that need to integrate
with several external services rather than just one or two, as it allows them to share a common configuration for the entire

  1. Add the Service API to your application's API modules:

  2. Add the Service Core to your application's internal implementations:

  3. Use your product's normal strategy for configuring the major components, which are:

  • AsapConfiguration (see the EnvVarAsapConfiguration and StringValuesAsapConfiguration implementations)
  • JwtClaimsValidator
  • AuthorizationHeaderGenerator (see the DefaultAuthorizationHeaderGenerator implementation)
  • AsapService (see the DefaultAsapService implementation)

Only the AsapService itself needs to be accessible through the application's API.


Let's say we have a Spring application that has a resource that requires ASAP auth.
We might want to write a Spring integration test for this that runs locally (doesn't talk to the actual ASAP servers).
Here's roughly how to do that:

  1. In your test/resources, create privatekeys/alice and publickeys/alice directories.

  2. Generate a private and public key as described above using openssl and put it in privatekeys/alice/test-key and publickeys/alice/test-key.

  3. In your Spring test, override the asap.public_key_repository.url property to classpath:///publickeys/.
    This will make the server part look for public keys in the test/resources/publickeys directory,
    assuming you use that property name to configure ASAP.

  4. When generating the request, point the header generator to test/resources/privatekeys:

    AuthorizationHeaderGenerator headerGenerator =
    Jwt jwt = JwtBuilder.newJwt()
    String value = headerGenerator.generateAuthorizationHeader(jwt);


Pull requests, issues and comments welcome. For pull requests:

  • Add tests for new features and bug fixes
  • Follow the existing style
  • Separate unrelated changes into multiple pull requests

See the existing issues for things to start contributing.

For bigger changes, make sure you start a discussion first by creating
an issue and explaining the intended change.

Atlassian requires contributors to sign a Contributor License Agreement,
known as a CLA. This serves as a record stating that the contributor is
entitled to contribute the code/documentation/translation to the project
and is willing to have it used in distributions and derivative works
(or is willing to transfer ownership).

Prior to accepting your contributions we ask that you please follow the appropriate
link below to digitally sign the CLA. The Corporate CLA is for those who are
contributing as a member of an organization and the individual CLA is for
those contributing as an individual.


Copyright (c) 2017 Atlassian and others.
Apache 2.0 licensed, see LICENSE.txt file.