Skip to content

Commit

Permalink
Add Banking Account Service example
Browse files Browse the repository at this point in the history
* Example for Auth using file user store

* Example of file user store

* Example for file user store

* Update api_gateway.bal

* Update api_gateway.bal

* Example for Auth using file user store

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Real World Example for Auth

* Real World Example for Auth

* Update api_gateway.bal

* Delete examples/banking-accounts-service/Ballerina.toml

* Write a Real World Example for Auth

* Write a Real World Example for Auth

* Write a Real World Example for Auth

* Update api_gateway.bal

* Update api_gateway.bal

* Create api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Rename public.cert to public.crt

* Create private.key

* Create public.crt

* Update Config.toml

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update Config.toml

* Update Config.toml

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Create Config.toml

* Update Config.toml

* Update Config.toml

* Update Config.toml

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway.bal

* Update api_gateway_test.bal

* Update api_gateway.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway_test.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update Config.toml

* Update Config.toml

* Update Ballerina.toml

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update Config.toml

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway_test.bal

* Update api_gateway.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway_test.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Update api_gateway_test.bal

* Create README.md

* Update README.md

* Update README.md

* Update README.md

* Update api_gateway.bal

* Update api_gateway_test.bal

* Update Config.toml

* Update README.md

* Update README.md

* Example : Banking Account Service with File Store Auth using scopes

* Apply suggestions from code review

Co-authored-by: DimuthuMadushan <35717653+DimuthuMadushan@users.noreply.github.com>
Co-authored-by: Thisaru Guruge <thisaru@wso2.com>

* Apply suggestions from code review

Co-authored-by: Thisaru Guruge <thisaru@wso2.com>
Co-authored-by: DimuthuMadushan <35717653+DimuthuMadushan@users.noreply.github.com>

* Update examples/banking-accounts-service/README.md

Co-authored-by: Thisaru Guruge <thisaru@wso2.com>

* Update README.md

* Update as per review comment for query

* Update examples/banking-accounts-service/api_gateway.bal

Co-authored-by: DimuthuMadushan <35717653+DimuthuMadushan@users.noreply.github.com>

* Update api_gateway.bal

* Update api_gateway.bal

* Update api_gateway.bal

* Update README.md

* Update examples/banking-accounts-service/api_gateway.bal

Co-authored-by: Thisaru Guruge <thisaru@wso2.com>

* Update examples/banking-accounts-service/README.md

Co-authored-by: DimuthuMadushan <35717653+DimuthuMadushan@users.noreply.github.com>

* Update examples/banking-accounts-service/README.md

Co-authored-by: DimuthuMadushan <35717653+DimuthuMadushan@users.noreply.github.com>

* Update examples/banking-accounts-service/README.md

Co-authored-by: DimuthuMadushan <35717653+DimuthuMadushan@users.noreply.github.com>

* Update api_gateway.bal

* Update api_gateway.bal

---------

Co-authored-by: DimuthuMadushan <35717653+DimuthuMadushan@users.noreply.github.com>
Co-authored-by: Thisaru Guruge <thisaru@wso2.com>
  • Loading branch information
3 people authored Oct 20, 2023
1 parent 9590a79 commit 4bd5ebb
Show file tree
Hide file tree
Showing 10 changed files with 545 additions and 0 deletions.
7 changes: 7 additions & 0 deletions examples/banking-accounts-service/Ballerina.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
org = "auth"
name = "banking_account_service"
version = "1.0.0"

[build-options]
observabilityIncluded = true
17 changes: 17 additions & 0 deletions examples/banking-accounts-service/Config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[[ballerina.auth.users]]
username = "alice"
password = "alice@123"
scopes = ["read-account", "read-balance", "funds-transfer"]

[[ballerina.auth.users]]
username = "bob"
password = "bob@123"
scopes = ["read-account", "read-balance"]

[[ballerina.auth.users]]
username = "david"
password = "david@123"
scopes = ["read-account"]

[ballerina.log]
level = "INFO"
119 changes: 119 additions & 0 deletions examples/banking-accounts-service/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# Secured Banking Account Management Service with File Store Basic Auth with Scopes

[![Star on Github](https://img.shields.io/badge/-Star%20on%20Github-blue?style=social&logo=github)](https://github.com/ballerina-platform/module-ballerina-auth)

_Authors_: [@harshalkh](https://github.com/harshalkh) \
_Reviewers_: @ThisaruGuruge @DimuthuMadushan \
_Created_: 2023/10/16 \
_Updated_: 2023/10/16

## Overview

This guide explains how to secure the 'Banking Account Management Service' (RESTful service) with Basic Auth using File Store in Ballerina.

The end-user (customer) in this example, Alice, Bob and David, interacts with the system using the web/mobile app provided. This web/mobile app acts as a 'Client' on behalf of the user’s actions and calls to the 'API Gateway'. The 'API Gateway' routes the requests to 'Banking Service', which is responsible for processing the requests for the customer.

> **NOTE:** For this guide, since discussion is about the File Store based Basic Auth security aspects, focus is on the network
interactions once the 'API Gateway' receives a request. The transaction data is stored locally in [table](https://ballerina.io/learn/by-example/table/)

- The 'API Gateway' intercepts the request from the end-user, extracts the credentials (username and password which is
concatenated with a `:` and Base64 encoded), and then talks to File Store Listener to validate the credentials.
- After validating the credentials, the 'API Gateway' talks to 'Banking Account Service' with mTLS (mutual TLS).
- The 'Banking Account Service' uses table data to process customer request based on their authorization scopes.

## Implementation

- You can get started with the 'API Gateway', which is responsible to authorize the requests using Basic Auth with the use of File user store and forward the request to the actual microservice via mTLS (mutual TLS). In this scenario, it is 'Banking Account Service'. The 'API Gateway' service is secured by setting the `auth` attribute of `http:ServiceConfig` with the Basic Auth - File user store configurations, so that the Ballerina HTTP service knows how to validate the credentials with the configured File user store from Config.toml. Once validated, the business logic defined inside the resource will get executed. In this case, it will call the 'Banking Account Service' via mTLS and return the response to the 'Client'.
- In addition to declarative approach for Authentication and Authorization, service uses [Imperative Approach](https://ballerina.io/spec/http/#912-imperative-approach) as service needs to have granular control on authorization of customer. For example knowing customer id of user to fetch account details, available balance before proceeding for execution of payment.

> **NOTE:** The rest of the components such as Database Management System are not implemented as the main purpose of this article is to showcase the Basic Auth functionalities. But for the completeness of the story, the API Gateway will return a response from the data stored on in-memory tables.
## Testing

You can run the 'API Gateway' that we developed above, in our local environment. In order to run this service you need to setup prerequisite of Ballerina. You can refer documentation [here](https://ballerina.io/learn/get-started/)

Now, navigate to [`examples`](../) directory and execute the following command.
```shell
$ bal run banking-accounts-service
```

The successful execution of the service should show us the following output.
```shell
Compiling source
auth/banking_account_service:1.0.0

Running executable
```

Now, you can test authentication and authorization checks being enforced on different actions by sending HTTP requests.
This example uses the Unit Tests to test each scenario as follows.

#### Without authentication

```ballerina
http:Response response = check testClient->get("/accounts/account");
test:assertEquals(response.statusCode, http:STATUS_UNAUTHORIZED);
```

#### Authenticating as anonymous user

```ballerina
map<string|string[]> headers = {
"Authorization": "Basic random"
};
http:Response response = check testClient->get("/accounts/account", headers);
test:assertEquals(response.statusCode, http:STATUS_UNAUTHORIZED);
```

#### Detailed scenarios:

| Scenario\User | Alice | Bob | David |
| --- | --- | --- | --- |
| Scopes | `read-account` `read-balance` `funds-transfer` | `read-account` `read-balance` | `read-account` |
| Accessing `GET /accounts/account` | `200` Account Details for Alice | `200` Account Details for Bob | `200` Account Details for David |
| Accessing `GET /accounts/balance` | `200` Account Details with Balance for Alice | `200` Account Details with Balance for Bob | `403` Forbidden |
| Accessing `POST /payments/transfer` where transaction amount within available balance | `200` Response with unique paymentId and status as SUCCESS | `403` Forbidden | `403` Forbidden |
| Accessing `POST /payments/transfer` where transaction amount higher than available balance| `200` Response with unique paymentId and status as FAILED | `403` Forbidden | `403` Forbidden |



## Deployment

Once the development is done, you can deploy the service using any of the methods that are listed below.

### Deploying Locally

Now, you can build Ballerina executable files (.jar) of the components that we developed above. Open the terminal and
navigate to [`examples/banking-account-service`](../banking-accounts-service/), and execute the following command for
each of them.

```shell
$ bal build
```

The successful execution of the above command should show us the following outputs in order.

```shell
Compiling source
auth/api_gateway:1.0.0

Generating executable
target/bin/api_gateway.jar
```

Once the `*.jar` file is created inside the `target/bin` directories, we can run the components with the following commands in order.

```shell
$ bal run target/bin/api_gateway.jar
```

### Deploying Code to Cloud

Ballerina code to cloud supports generating the deployment artifacts of the Docker and Kubernetes.
Refer to [Code to Cloud](https://ballerina.io/learn/code-to-cloud-deployment/) guide for more information.

## Observability

HTTP/HTTPS based Ballerina services and any client connectors are observable by default.
[Observing Ballerina Code](https://ballerina.io/learn/observe-ballerina-programs/#provide-observability-in-ballerina) guide provides
information on enabling Ballerina service observability with some of its supported systems.
180 changes: 180 additions & 0 deletions examples/banking-accounts-service/api_gateway.bal
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org) All Rights Reserved.
//
// WSO2 LLC. licenses this file to you under the Apache License,
// Version 2.0 (the "License"); you may not use this file except
// in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

import ballerina/auth;
import ballerina/http;
import ballerina/io;
import ballerina/uuid;

type Balance record {|
string name;
string amount;
string currency;
|};

type AccountWithBalances record {|
string id;
string accountNumber;
readonly string customerId;
string customerName;
string productType;
string status;
Balance[] balances;
|};

type PaymentRequest readonly & record {|
string amount;
string currency;
string creditor;
|};

type PaymentResponse readonly & record {|
string id;
string status;
string failureReason?;
|};

table<AccountWithBalances> key(customerId) accountBalances = table [
{
id: "vgshdkrokjhbbb",
accountNumber: "1234 1234 1234",
customerId: "alice",
customerName: "Alice Alice",
productType: "Savings Account",
status: "Active",
balances: [
{ name: "Available", amount: "1000", currency: "INR" },
{ name: "Ledger", amount: "1000", currency: "INR" },
{ name: "Uncleared", amount: "0", currency: "INR" }
]
},
{
id: "vgksurbkfldppd",
accountNumber: "1234 1234 6789",
customerId: "bob",
customerName: "Bob Bob",
productType: "Current Account",
status: "Active",
balances: [
{ name: "Available", amount: "10000", currency: "INR" },
{ name: "Ledger", amount: "1000", currency: "INR" },
{ name: "Uncleared", amount: "0", currency: "INR" }
]
},
{
id: "vgskspwldkdddn",
accountNumber: "1234 1234 2345",
customerId: "david",
customerName: "David David",
productType: "Savings Account",
status: "Active",
balances: [
{ name: "Available", amount: "8000", currency: "INR" },
{ name: "Ledger", amount: "1000", currency: "INR" },
{ name: "Uncleared", amount: "0", currency: "INR" }
]
}
];

listener http:Listener apiGateway = new (9090,
secureSocket = {
key: {
certFile: "../banking-accounts-service/resources/public.crt",
keyFile: "../banking-accounts-service/resources/private.key"
}
}
);

// Imperative approach as we need to know about customer authozation details for filtering data
// https://ballerina.io/spec/http/#912-imperative-approach
http:FileUserStoreConfig config = {};
http:ListenerFileUserStoreBasicAuthHandler handler = new (config);

@http:ServiceConfig {
auth: [
{
fileUserStoreConfig: {},
scopes: ["read-account"]
}
]
}
service /accounts on apiGateway {
resource function get account(@http:Header string? Authorization) returns AccountWithBalances[] {
string customerId = getCustomerId(Authorization);
AccountWithBalances[] accountBalance = from AccountWithBalances account in accountBalances
where account.customerId == customerId
select account;
AccountWithBalances[] accountBalance1 = accountBalance.clone();
accountBalance1[0].balances = [];
return accountBalance1;
}

@http:ResourceConfig {
auth: [
{
fileUserStoreConfig: {},
scopes: ["read-balance"]
}
]
}
resource function get balances(@http:Header string? Authorization) returns AccountWithBalances[] {
string customerId = getCustomerId(Authorization);
AccountWithBalances[] accountBalance = from AccountWithBalances account in accountBalances
where account.customerId == customerId
select account;
return accountBalance;
}
}

@http:ServiceConfig {
auth: [
{
fileUserStoreConfig: {},
scopes: ["funds-transfer"]
}
]
}
service /payments on apiGateway {
resource function post transfer(@http:Payload PaymentRequest paymentRequest, @http:Header string? Authorization) returns PaymentResponse {
string customerId = getCustomerId(Authorization);
AccountWithBalances[] accountBalance = from AccountWithBalances account in accountBalances
where account.customerId == customerId
select account;
boolean balAvailable = accountBalance[0].balances
.filter(bal => bal.name=="Available").some(bal1 => bal1.amount>=paymentRequest.amount);
if !balAvailable {
io:println("Insufficient Balance in account");
return {
id: uuid:createType4AsString(),
status: "FAILED",
failureReason: "Insufficient Balance in account"
};
}
return {
id: uuid:createType4AsString(),
status: "SUCCESS"
};
}
}

public function getCustomerId(string? authorization) returns string {
auth:UserDetails|http:Unauthorized authn = handler.authenticate(authorization is () ? "" : authorization);
string customerId = "";
if authn is auth:UserDetails {
customerId = authn.username;
}
return customerId;
}
28 changes: 28 additions & 0 deletions examples/banking-accounts-service/resources/private.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCBXKLp9WJUuJko
SfDn3HM2LWVxiHrP11me6D4X2AqoUiCZ1w976q1LuBlzWNhONYwJvHXewUuRmo0d
4NRp2ma0qjdMN246XWyozpzPfJdvovfiT+V6HnSbMg82ZppfF3e85Cgrg6mSA7Wf
faaHr62SnexseZ9ioNCuRUrW2Zg208l99IItP4K4iGclQlyjs3S6drH7JJk3rv8B
f76wmmoCEAhknOtGLq543dEUIjFgNdIy/GsSY52fiA4LSjUCv27kGn03nayqoZs3
XHqM0qLdt9SPXbYe7l75j0o6Z9tyGFCKXY/zVwiLfRUqDIOfkN5YS4Ohit52Tj7q
oBmvEzD7AgMBAAECggEAXM/F4u23OummmQ1T1kaIMpqnaalt06jCGAywYBMUsmca
FMYDyfg5lVXkjKl1p8crTeD1AHjWawTjskgYnkmf3ocxXXF3mFBnIUX7o7HURLg7
+RcxoUgwiRiFaZZ7szX3JoLbfzzbcHNQ37kavccBVWwQsFMiU3Tlw+LbKwK6/row
LYsQPx7gT4u7hViat4vQDTYcgyjvvFCiek4ndL6O9K49MxIMU678UXB6ia5iUevy
vgEfcYkKQ5EQ38qS3ZwsubPvj4633jvAJRr/hJD8XINZC74kTXeV3BGH2LlpQOEq
kWkOypwYNjnXtt1JO8+Iu6mEXKUoiIBPfGrJ3vDSQQKBgQDmYPc7kfYan/LHjJRv
iE2CwbC26yVA6+BEPQv9z7jChO9Q6cUbGvM8EEVNpC9nmFogkslzJhz55HP84QZL
u3ptU+D96ncq6zkBqxBfRnZG++D36+XRXIwzz3h+g1Nwrl0y0MFbwlkMm3ZqJdd6
pZz1FZGd6zvQftW8m7jPSKHuswKBgQCPv6czFOZR6bI+qCQdaORpe9JGoAduOD+4
YKl96s0eiAKhkGhFCrMd6GJwWRkpNcfwB+J9sMahORbfvwiYanI56h7Vi30DFPRb
m1m8dLkr6z+8bxMxKJaMXIIjy3UDamgDr7QHInNUih2iGvtB8QqZ0aobsB2XIxZg
qESTMcpYmQKBgHSwSqneraQgvgz7FLhFdtUzHDoacr0mfGqz7R37F99XDAyUy+SF
ywvyRdgkwGodjhEPqH/tnyGn6GP+6nxzknhL0xtppkCT8kT5C4rmmsQrknChCL/5
u34GqUaTaDEb8FLrz/SVRRuQpvLvBey2dADjkuVFH//kLoig64P6iyLnAoGBAIlF
g+2L78YZXVXoS1SqbjUtQUigWXgvzunLpQ/Rwb9+MsUGmgwUg6fz2s1eyGBKM3xM
i0VsIsKjOezBCPxD6oDTyk4yvlbLE+7HE5KcBJikNmFD0RgIonu3e6+jA0MXweyD
RW/qviflHRdInNgDzxPE3KVEMX26zAvRpGrMCWdBAoGAdQ5SvX+mAC3cKqoQ9Zal
lSqWoyjfzP5EaVRG8dtoLxbznQGTTvtHXc65/MznX/L9qkWCS6Eb4HH5M3hFNY46
LNIzGQLznE1odwv7H5B8c0/m3DrKTxbh8bYcrR1BW5/nKZNNW7k1O6OjEozvAajK
JQdp3KBU9S8CmBjGrRpJ2qw=
-----END PRIVATE KEY-----
21 changes: 21 additions & 0 deletions examples/banking-accounts-service/resources/public.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
-----BEGIN CERTIFICATE-----
MIIDdzCCAl+gAwIBAgIEfP3e8zANBgkqhkiG9w0BAQsFADBkMQswCQYDVQQGEwJV
UzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxDTALBgNVBAoT
BFdTTzIxDTALBgNVBAsTBFdTTzIxEjAQBgNVBAMTCWxvY2FsaG9zdDAeFw0xNzEw
MjQwNTQ3NThaFw0zNzEwMTkwNTQ3NThaMGQxCzAJBgNVBAYTAlVTMQswCQYDVQQI
EwJDQTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzENMAsGA1UEChMEV1NPMjENMAsG
A1UECxMEV1NPMjESMBAGA1UEAxMJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEAgVyi6fViVLiZKEnw59xzNi1lcYh6z9dZnug+F9gKqFIg
mdcPe+qtS7gZc1jYTjWMCbx13sFLkZqNHeDUadpmtKo3TDduOl1sqM6cz3yXb6L3
4k/leh50mzIPNmaaXxd3vOQoK4OpkgO1n32mh6+tkp3sbHmfYqDQrkVK1tmYNtPJ
ffSCLT+CuIhnJUJco7N0unax+ySZN67/AX++sJpqAhAIZJzrRi6ueN3RFCIxYDXS
MvxrEmOdn4gOC0o1Ar9u5Bp9N52sqqGbN1x6jNKi3bfUj122Hu5e+Y9KOmfbchhQ
il2P81cIi30VKgyDn5DeWEuDoYredk4+6qAZrxMw+wIDAQABozEwLzAOBgNVHQ8B
Af8EBAMCBaAwHQYDVR0OBBYEFNmtrQ36j6tUGhKrfW9qWWE7KFzMMA0GCSqGSIb3
DQEBCwUAA4IBAQAv3yOwgbtOu76eJMl1BCcgTFgaMUBZoUjK9Un6HGjKEgYz/YWS
ZFlY/qH5rT01DWQevUZB626d5ZNdzSBZRlpsxbf9IE/ursNHwHx9ua6fB7yHUCzC
1ZMp1lvBHABi7wcA+5nbV6zQ7HDmBXFhJfbgH1iVmA1KcvDeBPSJ/scRGasZ5q2W
3IenDNrfPIUhD74tFiCiqNJO91qD/LO+++3XeZzfPh8NRKkiPX7dB8WJ3YNBuQAv
gRWTISpSSXLmqMb+7MPQVgecsepZdk8CwkRLxh3RKPJMjigmCgyvkSaoDMKAYC3i
YjfUTiJ57UeqoSl0IaOFJ0wfZRFh+UytlDZa
-----END CERTIFICATE-----
17 changes: 17 additions & 0 deletions examples/banking-accounts-service/tests/Config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[[ballerina.auth.users]]
username = "alice"
password = "alice@123"
scopes = ["read-account", "read-balance", "funds-transfer"]

[[ballerina.auth.users]]
username = "bob"
password = "bob@123"
scopes = ["read-account", "read-balance"]

[[ballerina.auth.users]]
username = "david"
password = "david@123"
scopes = ["read-account"]

[ballerina.log]
level = "INFO"
Loading

0 comments on commit 4bd5ebb

Please sign in to comment.