Introduction
This tutorial provides a step-by-step guide on securing a Quarkus backend application using IBM App ID.
Configure IBM App ID
Login to IBM Cloud and create an App ID instance using the lite (free) plan.
Then create an application as a regular web app. Next, create a test user using Cloud Directory -> Users menu.
Configure Quarkus
First, update Maven pom.xml
:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-oidc</artifactId>
</dependency>
Next, find the client ID/secret/login URL in IBM App id application details:
And then enter them into application.properties
:
quarkus.oidc.auth-server-url=https://eu-de.appid.cloud.ibm.com/oauth/v4/xxxx-0839-463f-a816-22ba90f44ee2
quarkus.oidc.client-id=xxxx-40d0-486d-af5f-16e2a4c4f837
quarkus.oidc.credentials.secret=xxxxMzhkMGQ2
Next, add some resources that need authentication, like the one bellow:
package org.acme.rest.json;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import org.eclipse.microprofile.jwt.Claims;
import org.eclipse.microprofile.jwt.JsonWebToken;
import org.jboss.resteasy.reactive.NoCache;
import io.quarkus.security.Authenticated;
import io.quarkus.security.identity.SecurityIdentity;
@Path("/api/users")
@Authenticated
public class UsersResource {
@Inject
SecurityIdentity securityIdentity;
@Inject
JsonWebToken accessToken;
@GET
@Path("/me")
@NoCache
public User me() {
return new User(securityIdentity);
}
public static class User {
private final String userName;
User(SecurityIdentity securityIdentity) {
this.userName = securityIdentity.getPrincipal().getName();
}
public String getUserName() {
return userName;
}
}
}
Test the application
First, run the quarkus app using:
./mvnw quarkus:dev
Then, get a token using curl
command and replacing the <useremail>
/<password>
with the above username and password. Also, replace <auth>
with the Base64-encoded string of the application clientid:secret .
curl -X POST "https://eu-de.appid.cloud.ibm.com/oauth/v4/XXXX-0839-463f-a816-22ba90f44ee2/token" -H "Authorization: Basic <auth>" -H "Accept: application/json" -F "grant_type=password" -F "username=<useremail>" -F "password=<password>"
The response should look like the one bellow:
{
"access_token": "xxxx,
"id_token": "yyyy",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "openid appid_default appid_readuserattr appid_readprofile appid_writeuserattr appid_authenticated"
}
The access_token
is the one you need for backend access. By default, it looks like:
Header:
{
"alg": "RS256",
"typ": "JWT",
"kid": "appId-39a37f57-a227-4bfe-a044-93b6e6050a61-2018-08-02T11:57:43.401",
"ver": 4
}
Payload:
{
"iss": "https://us-south.appid.cloud.ibm.com/oauth/v4/39a37f57-a227-4bfe-a044-93b6e6050a61",
"exp": 1551903163,
"aud": [
"968c2306-9aef-4109-bc06-4f5ed6axi24a"
],
"sub": "2b96cc04-eca5-4122-a8de-6e07d14c13a5",
"email_verified": true,
"amr": [
"cloud_directory"
],
"iat": 1551899553,
"tenant": "39a37f57-a227-4bfe-a044-93b6e6050a61",
"scope": "openid appid_default appid_readprofile appid_readuserattr appid_writeuserattr appid_authenticated"
}
The id_token
is a token that contains information about the user. By default, it looks like:
Header:
{
"alg": "RS256",
"typ": "JWT",
"kid": "appId-39a37f57-a227-4bfe-a044-93b6e6050a61-2018-08-02T11:57:43.401",
"ver": 4
}
Payload:
{
"iss": "https://us-south.appid.cloud.ibm.com/oauth/v4/39a37f57-a227-4bfe-a044-93b6e6050a61",
"aud": [
"968c2306-9aef-4109-bc06-4f5ed6axi24a"
],
"exp": 1551903163,
"tenant": "39a37f57-a227-4bfe-a044-93b6e6050a61",
"iat": 1551899553,
"email": "appid155@mailinator.com",
"name": "appid155@mailinator.com",
"sub": "2b96cc04-eca5-4122-a8de-6e07d14c13a5",
"email_verified": true,
"identities": [
{
"provider": "cloud_directory",
"id": "118c0278-3526-4954-876b-cf70eb88efa2"
}
],
"amr": [
"cloud_directory"
]
}
Now, finaly let’s call out api usign a command similar the this one:
curl -v -X GET "http://127.0.0.1:8080/api/users/email" -H "Authorization: Bearer <token>"
If everything it’s ok, you shoud receive the user id as response.
{"userName":"XXXX-15dc-4103-a604-66265c439c73"}
Documentation and links:
- Access and Identity tokens - https://cloud.ibm.com/docs/appid?topic=appid-tokens&interface=ui&code=curl
- Quarkus tutorial of protecting a service application by using OpenID Connect (OIDC) Bearer token authentication - https://quarkus.io/guides/security-oidc-bearer-token-authentication-tutorial