import ballerina/http;
import ballerina/config;
import ballerina/jwt;
import ballerina/log;
jwt:InboundJwtAuthProvider jwtAuthProvider = new ({
    issuer: "ballerina",
    audience: "ballerina.io",
    trustStoreConfig: {
        certificateAlias: "ballerina",
        trustStore: {
            path: config:getAsString("b7a.home") +
                  "/bre/security/ballerinaTruststore.p12",
            password: "ballerina"
        }
    }
});
http:BearerAuthHandler jwtAuthHandler = new (jwtAuthProvider);
listener http:Listener ep = new (9090, config = {
    auth: {
        authHandlers: [jwtAuthHandler]
    },
    secureSocket: {
        keyStore: {
            path: config:getAsString("b7a.home") +
                  "/bre/security/ballerinaKeystore.p12",
            password: "ballerina"
        }
    }
});@http:ServiceConfig {
    basePath: "/hello"
}
service echo on ep {
    @http:ResourceConfig {
        methods: ["GET"],
        path: "/sayHello",
        auth: {
            scopes: ["hello"],
            enabled: true
        }
    }
    resource function hello(http:Caller caller, http:Request req) {
        error? result = caller->respond("Hello, World!!!");
        if (result is error) {
            log:printError("Error in responding to caller", result);
        }
    }
}# To run the service, execute the command below by passing Ballerina home path
# as a system property.
ballerina run secured_service_with_jwt_auth.bal --b7a.home=<ballerina_home_path>
[ballerina/http] started HTTPS/WSS listener 0.0.0.0:9090
curl -k -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.\
eyJzdWIiOiJiYWxsZXJpbmEiLCJpc3MiOiJiYWxsZXJpbmEiLCJleHAiOjI4MTg0MTUwMTksIm\
lhdCI6MTUyNDU3NTAxOSwianRpIjoiZjVhZGVkNTA1ODVjNDZmMmI4Y2EyMzNkMGMyYTNjOWQi\
LCJhdWQiOlsiYmFsbGVyaW5hIiwiYmFsbGVyaW5hLm9yZyIsImJhbGxlcmluYS5pbyJdLCJzY2\
9wZSI6ImhlbGxvIn0.bNoqz9_DzgeKSK6ru3DnKL7NiNbY32ksXPYrh6Jp0_O3ST7WfXMs9WVk\
x6Q2TiYukMAGrnMUFrJnrJvZwC3glAmRBrl4BYCbQ0c5mCbgM9qhhCjC1tBA50rjtLAtRW-JTR\
pCKS0B9_EmlVKfvXPKDLIpM5hnfhOin1R3lJCPspJ2ey_Ho6fDhsKE3DZgssvgPgI9PBItnkip\
Q3CqqXWhV-RFBkVBEGPDYXTUVGbXhdNOBSwKw5ZoVJrCUiNG5XD0K4sgN9udVTi3EMKNMnVQaq\
399k6RYPAy3vIhByS6QZtRjOG8X93WJw-9GLiHvcabuid80lnrs2-mAEcstgiHVw" \
https://localhost:9090/hello/sayHello
Hello, World!!!

Secured Service with JWT Auth

A service can be secured using JWT and optionally, by enforcing authorization. The JWT auth provider verifies the signature of the JWT token sent in the Authorization header. For this, Ballerina should trust the JWT issuer (the certificate of the JWT issuer must be present in the Ballerina certificate truststore). Ballerina uses the concept of scopes for authorization. A resource declared in a service can be bound to one/more scope(s). The scope can be included in the JWT using the scope attribute. In the authorization phase, the scopes of the resource are compared against the scopes mapped to the user for at least one match between the two sets.

import ballerina/http;
import ballerina/config;
import ballerina/jwt;
import ballerina/log;
jwt:InboundJwtAuthProvider jwtAuthProvider = new ({
    issuer: "ballerina",
    audience: "ballerina.io",
    trustStoreConfig: {
        certificateAlias: "ballerina",
        trustStore: {
            path: config:getAsString("b7a.home") +
                  "/bre/security/ballerinaTruststore.p12",
            password: "ballerina"
        }
    }
});

Creates an inbound JWT authentication provider with the relevant configurations.

http:BearerAuthHandler jwtAuthHandler = new (jwtAuthProvider);

Creates a Bearer Auth handler with the created JWT Auth provider.

listener http:Listener ep = new (9090, config = {
    auth: {
        authHandlers: [jwtAuthHandler]
    },

The endpoint used here is the http:Listener. The JWT authentication handler is set to this endpoint using the authHandlers attribute. It is optional to override the authentication and authorization at the service and resource levels.

    secureSocket: {
        keyStore: {
            path: config:getAsString("b7a.home") +
                  "/bre/security/ballerinaKeystore.p12",
            password: "ballerina"
        }
    }
});

The secure hello world sample uses HTTPS.

@http:ServiceConfig {
    basePath: "/hello"
}
service echo on ep {
    @http:ResourceConfig {
        methods: ["GET"],
        path: "/sayHello",
        auth: {
            scopes: ["hello"],
            enabled: true
        }
    }

The Auth configuration comprises of two parts - authentication & authorization. Authentication can be disabled by setting the enabled: false flag. Authorization is based on scopes. A scope maps to one or more groups. For a user to access a resource, the user should be in the same groups as the scope. To specify one or more scope of a resource, the annotation attribute scopes can be used.

    resource function hello(http:Caller caller, http:Request req) {
        error? result = caller->respond("Hello, World!!!");
        if (result is error) {
            log:printError("Error in responding to caller", result);
        }
    }
}

The authentication and authorization settings can be overridden at the resource level. The hello resource would inherit the enabled: true flag from the service level, which is set automatically. The scope of the resource is defined as “hello”.

# To run the service, execute the command below by passing Ballerina home path
# as a system property.
ballerina run secured_service_with_jwt_auth.bal --b7a.home=<ballerina_home_path>
[ballerina/http] started HTTPS/WSS listener 0.0.0.0:9090
curl -k -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.\
eyJzdWIiOiJiYWxsZXJpbmEiLCJpc3MiOiJiYWxsZXJpbmEiLCJleHAiOjI4MTg0MTUwMTksIm\
lhdCI6MTUyNDU3NTAxOSwianRpIjoiZjVhZGVkNTA1ODVjNDZmMmI4Y2EyMzNkMGMyYTNjOWQi\
LCJhdWQiOlsiYmFsbGVyaW5hIiwiYmFsbGVyaW5hLm9yZyIsImJhbGxlcmluYS5pbyJdLCJzY2\
9wZSI6ImhlbGxvIn0.bNoqz9_DzgeKSK6ru3DnKL7NiNbY32ksXPYrh6Jp0_O3ST7WfXMs9WVk\
x6Q2TiYukMAGrnMUFrJnrJvZwC3glAmRBrl4BYCbQ0c5mCbgM9qhhCjC1tBA50rjtLAtRW-JTR\
pCKS0B9_EmlVKfvXPKDLIpM5hnfhOin1R3lJCPspJ2ey_Ho6fDhsKE3DZgssvgPgI9PBItnkip\
Q3CqqXWhV-RFBkVBEGPDYXTUVGbXhdNOBSwKw5ZoVJrCUiNG5XD0K4sgN9udVTi3EMKNMnVQaq\
399k6RYPAy3vIhByS6QZtRjOG8X93WJw-9GLiHvcabuid80lnrs2-mAEcstgiHVw" \
https://localhost:9090/hello/sayHello
Hello, World!!!

Invoke the service using “cURL”. Note that it is required to provide the correct bearer authentication header with the cURL command.