Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions .github/workflows/build-oauth2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Fineract Gradle build - oauth2
on: [push, pull_request]

jobs:
build:
runs-on: ubuntu-20.04

services:
mariad:
image: mariadb:10.6
ports:
- 3306:3306
env:
MARIADB_ROOT_PASSWORD: mysql
options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3

mock-oauth2-server:
image: ghcr.io/navikt/mock-oauth2-server:0.4.0
ports:
- 9000:9000
env:
SERVER_PORT: 9000
JSON_CONFIG: '{ "interactiveLogin": true, "httpServer": "NettyWrapper", "tokenCallbacks": [ { "issuerId": "auth/realms/fineract", "tokenExpiry": 120, "requestMappings": [{ "requestParam": "scope", "match": "fineract", "claims": { "sub": "mifos", "scope": [ "test" ] } } ] } ] }'

env:
TZ: Asia/Kolkata
steps:
- name: Set up cache
uses: actions/cache@v2
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-oauth2-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-oauth2-
- name: Checkout
uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v2
with:
java-version: '11'
distribution: 'zulu'
- name: Validate Gradle wrapper
uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b
- name: Verify MariaDB connection
run: |
while ! mysqladmin ping -h"127.0.0.1" -P3306 ; do
sleep 1
done
- name: Initialise databases
run: |
./gradlew --no-daemon -q createDB -PdbName=fineract_tenants
./gradlew --no-daemon -q createDB -PdbName=fineract_default
- name: Install additional software
run: |
sudo apt-get update
sudo apt-get install ghostscript -y
- name: Build & Test
run: ./gradlew --no-daemon -q --console=plain build test --fail-fast -x :integration-tests:test -x :twofactor-tests:test -Psecurity=oauth
6 changes: 3 additions & 3 deletions .github/workflows/build-twofactor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ jobs:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
key: ${{ runner.os }}-gradle-twofactor-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
${{ runner.os }}-gradle-twofactor-
- name: Checkout
uses: actions/checkout@v2
- name: Set up JDK 11
Expand All @@ -49,4 +49,4 @@ jobs:
sudo apt-get update
sudo apt-get install ghostscript -y
- name: Build & Test
run: ./gradlew --no-daemon -q --console=plain build test --fail-fast -x :integration-tests:test -Ptwofactor=enabled
run: ./gradlew --no-daemon -q --console=plain build test --fail-fast -x :integration-tests:test -x :oauth2-tests:test -Ptwofactor=enabled
6 changes: 3 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ jobs:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
key: ${{ runner.os }}-gradle-basicauth-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
${{ runner.os }}-gradle-basicauth-
- name: Checkout
uses: actions/checkout@v2
- name: Set up JDK 11
Expand All @@ -48,4 +48,4 @@ jobs:
sudo apt-get update
sudo apt-get install ghostscript -y
- name: Build & Test
run: ./gradlew --no-daemon -q --console=plain licenseMain licenseTest check build test --fail-fast doc -x :twofactor-tests:test
run: ./gradlew --no-daemon -q --console=plain licenseMain licenseTest check build test --fail-fast doc -x :twofactor-tests:test -x :oauth2-test:test
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ build
*.iml
*.ipr
*.iws
*.swp
*.DS_Store
.idea
.vscode
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ buildscript {
'fineract-provider',
'integration-tests',
'twofactor-tests',
'oauth2-tests',
'fineract-client'
].contains(it.name)
}
Expand Down Expand Up @@ -111,7 +112,6 @@ allprojects {
// We do not use :+ to get the latest available version available on Maven Central, as that could suddenly break things.
// We use the Renovate Bot to automatically propose Pull Requests (PRs) when upgrades for all of these versions are available.

dependency 'org.springframework.security.oauth:spring-security-oauth2:2.5.1.RELEASE'
dependency 'org.apache.openjpa:openjpa:3.2.0' // when upgrading, also change OpenJPA version repeated above in buildscript!
dependency 'com.google.guava:guava:31.0.1-jre'
dependency 'com.google.code.gson:gson:2.8.9'
Expand Down
49 changes: 37 additions & 12 deletions fineract-doc/src/docs/en/03_oauth.adoc
Original file line number Diff line number Diff line change
@@ -1,41 +1,66 @@
== OAuth

Fineract has (basic) OAuth (2.0?) support. Here's how to use it:
Fineract has a (basic) OAuth2 support based on Spring Boot Security. Here's how to use it:

=== Build

You must re-build the distribution JAR (or WAR) using the special `-Psecurity=oauth` flag:

----
./gradlew bootJAR -Psecurity=oauth
java -jar build/libs/fineract-provider.jar
./gradlew bootRun -Psecurity=oauth
----

Downloads from https://fineract.apache.org, or using e.g. the https://hub.docker.com/r/apache/fineract container image, or on https://www.fineract.dev, this will not work, because they have not been built using this flag.

=== Invoke `/fineract-provider/api/oauth/token`
Previous versions of Fineract included a built-in authorisation server for issuing OAuth tokens. However, as the spring-security-oauth2 package was deprecated and replaced by built-in OAuth support in Spring Security, this is no longer supported as part of the package. Instead, you need to run a separate OAuth authorization server (e.g. https://github.com/spring-projects/spring-authorization-server) or use a 3rd-party OAuth authorization provider (https://en.wikipedia.org/wiki/List_of_OAuth_providers)

This instruction describes how to get Fineract OAuth working with a Keycloak (http://keycloak.org) based authentication provider running in a Docker container. The steps required for other OAuth providers will be similar.

=== Set up Keycloak

1. From terminal, run: 'docker run -p 9000:8080 -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin quay.io/keycloak/keycloak:15.0.2'
1. Go to URL 'http://localhost:9000/auth/admin' and login with admin/admin
1. Hover your mouse over text "Master" and click on "Add realm"
1. Enter name "fineract" for your realm
1. Click on tab "Users" on the left, then "Add user" and create user with username "mifos"
1. Click on tab "Credentials" at the top, and set password to "password", turning "temporary" setting to off
1. Click on tab "Clients" on the left, and create client with ID 'community-app'
1. In settings tab, set 'access-type' to 'confidential' and enter 'localhost' in the valid redirect URIs.
1. In credentials tab, copy string in field 'secret' as this will be needed in the step to request the access token

Finally we need to change Keycloak configuration so that it uses the username as a subject of the token:

1. Choose client 'community-app' in the tab 'Clients'
1. Go to tab 'Mappers' and click on 'Create'
1. Enter 'usernameInSub' as 'Name'
1. Choose mapper type 'User Property'
1. Enter 'username' into the field 'Property' and 'sub' into the field 'Token Claim Name'. Choose 'String' as 'Claim JSON Type'

You are now ready to test out OAuth:

=== Retrieve an access token from Keycloak

----
curl [--insecure] --location --request POST \
'https://localhost:8443/fineract-provider/api/oauth/token' \
--header 'Fineract-Platform-TenantId: default' \
curl --location --request POST \
'http://localhost:9000/auth/realms/fineract/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'username=mifos' \
--data-urlencode 'password=password' \
--data-urlencode 'client_id=community-app' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'client_secret=123'
--data-urlencode 'client_secret=<enter the client secret from credentials tab>'
----

Note that the `client_id` and `client_secret` are stored in the `oauth_client_details` table in the database.
The reply should contain a field 'access_token'. Copy the field's value and use it in the API call below:

=== Invoke APIs and pass `Authorization: bearer ...` header

----
curl --location --request GET \
'https://localhost:8443/fineract-provider/api/v1/clients' \
'https://localhost:8443/fineract-provider/api/v1/offices' \
--header 'Fineract-Platform-TenantId: default' \
--header 'Authorization: bearer RzfUyQ0wEnxxq4PyFCF1J-XGFCI'
--header 'Authorization: bearer <enter the value of the access_token field>'

----

NOTE: See also https://demo.fineract.dev/fineract-provider/api-docs/apiLive.htm#authentication_oauth
NOTE: See also https://demo.fineract.dev/fineract-provider/api-docs/apiLive.htm#authentication_oauth
2 changes: 1 addition & 1 deletion fineract-provider/dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ dependencies {
'org.springframework.boot:spring-boot-starter-web',
'org.springframework.boot:spring-boot-starter-security',
'org.springframework.boot:spring-boot-starter-cache',
'org.springframework.boot:spring-boot-starter-oauth2-resource-server',

'org.glassfish.jersey.media:jersey-media-multipart:2.35',

'org.springframework:spring-jms',
'org.springframework:spring-context-support',
'org.springframework.security.oauth:spring-security-oauth2',

'com.google.guava:guava',
'com.google.code.gson:gson',
Expand Down
3 changes: 3 additions & 0 deletions fineract-provider/properties/oauth/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,6 @@ management.endpoints.web.exposure.include=health,info

# FINERACT-914
server.forward-headers-strategy=framework

# OAuth authorisation server endpoint
spring.security.oauth2.resourceserver.jwt.issuer-uri: http://localhost:9000/auth/realms/fineract
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,6 @@ management.endpoints.web.exposure.include=health,info

# FINERACT-914
server.forward-headers-strategy=framework

# OAuth authorisation server endpoint
spring.security.oauth2.resourceserver.jwt.issuer-uri: http://localhost:9000/auth/realms/fineract

This file was deleted.

Loading