An open API service indexing awesome lists of open source software.

https://github.com/backbase/authorization-server

Mastercard OpenBanking Connect - Account Information Authorization Server
https://github.com/backbase/authorization-server

Last synced: 2 months ago
JSON representation

Mastercard OpenBanking Connect - Account Information Authorization Server

Awesome Lists containing this project

README

          

# Authorization Server for Mastercard OpenBanking Connect

## Overview

The Authorization Server is a Spring Security OAuth2 Authorization Server implementation that facilitates the **Account Information Services (AIS)** consent flow for [Mastercard OpenBanking Connect](https://developer.mastercard.com/open-banking-connect/documentation/). It implements the OAuth2 and OpenID Connect (OIDC) protocols to [Exchange the PSU Authorization for Access Consent](https://developer.mastercard.com/open-banking-connect/documentation/aisfeatures/exchange-psu-consent/) using the [Account Information Services API](https://developer.mastercard.com/open-banking-connect/documentation/aisfeatures/overview/).

This server acts as an intermediary between Backbase's Digital Banking Platform and Mastercard's OpenBanking Connect, handling the complex consent authorization flow required for accessing account information.

## Architecture

### Key Components

```
authorization-server
├── ais/ # Account Information Service specific components
│ ├── authentication/ # Custom authentication flow for AIS consents
│ ├── config/ # AIS and OpenBanking API configuration
│ ├── model/ # AIS domain models
│ └── repository/ # AIS consent user repository
├── security/ # Security configuration and token management
│ ├── authentication/ # OAuth2 authentication customizations
│ ├── config/ # Security and OAuth2 server configuration
│ └── token/ # Custom token claim mapping
└── validator/ # Redirect URI validation
```

### Authentication Flow

The server implements a custom authentication flow for AIS consent:

1. **Consent Initiation** - Client requests authorization
2. **SCA Redirect** - User redirected to Mastercard's SCA interface
3. **Consent Authorization** - User authorizes consent at ASPSP
4. **Callback Processing** - Authorization code exchanged for consent
5. **Token Issuance** - Access token issued with consent claims

## Features

### 1. OAuth2 Authorization Server

**Standards Compliance:**
- OAuth 2.0 Authorization Framework (RFC 6749)
- OpenID Connect 1.0
- OAuth 2.0 Authorization Code Grant
- Client Credentials Grant
- Refresh Token Grant

**Endpoints:**
- `/oauth2/authorize` - Authorization endpoint
- `/oauth2/token` - Token endpoint
- `/oauth2/jwks` or custom JWK set endpoint
- `/protocol/openid-connect/userinfo` - UserInfo endpoint
- `/protocol/openid-connect/certs` - JWKS endpoint

### 2. AIS Consent Management

**Consent Initiation** (`AiConsentRedirectEntryPoint`)
- Creates consent request with Mastercard OpenBanking Connect
- Configures permissions (default: ALLPSD2)
- Sets consent validity period
- Generates SCA redirect URL
- Includes callback URL with ASPSP identification

**Consent Authorization** (`AiConsentAuthenticationProvider`)
- Exchanges authorization code for consent
- Retrieves consent ID from Mastercard
- Maps consent to configured user
- Builds authenticated principal with ASPSP and consent claims

**Callback Handling** (`AiConsentCallbackFilter`)
- Processes OAuth callback from Mastercard SCA
- Extracts authorization query parameters
- Triggers consent authentication flow

### 3. Custom Token Claims

**Attribute Claim Mapper** (`AttributeClaimMapper`)
- Maps user attributes to JWT claims
- Supports custom claim configuration per client
- Configurable claim inclusion in:
- ID Token
- Access Token
- UserInfo endpoint response

**Standard Claims:**
- `sub` - User subject identifier
- `aspspId` - Account Servicing Payment Service Provider ID
- `consentId` - Consent identifier from Mastercard
- `preferred_username` - User's preferred username

### 4. Multi-ASPSP Support

The server supports multiple ASPSPs with individual configurations:
- ASPSP-specific permissions
- Configurable consent validity periods
- User mapping per ASPSP
- Fallback to default ASPSP

### 5. Security Features

**Client Authentication Methods:**
- `client_secret_basic` - HTTP Basic authentication
- `none` - Public clients (PKCE recommended)

**Token Security:**
- RSA-signed JWTs (RS256)
- Dynamically generated JWK Set
- Configurable token lifetimes
- Refresh token rotation

**Redirect URI Validation:**
- Allowlist-based validation
- Permissive mode for development
- Protection against open redirects

## Technical Stack

- **Framework:** Spring Boot 2.7.10
- **Java Version:** 17
- **Security:** Spring Security OAuth2 Authorization Server 0.4.1
- **API Generation:** OpenAPI Generator
- **Distributed Tracing:** Spring Cloud Sleuth
- **Build Tool:** Maven
- **Containerization:** Jib

## Configuration

### Application Properties

**Server Configuration:**
```yaml
server:
port: 8081
```

**Mastercard OpenBanking Connect API:**
```yaml
mastercard:
mcob:
api:
base-uri: https://developer.mastercard.com/apigwproxy/openbanking/connect/api
proxy:
enabled: false
host: proxy.example.com
port: 8080
ais:
aspsps:
- id: 420e5cff-0e2a-4156-991a-f6eeef0478cf # ASPSP identifier
permissions:
- ALLPSD2 # Or specific permissions
consent-validity: PT15M # ISO-8601 duration
available-consents:
- user:
username: sara
roles:
- USER
```

**Security Configuration:**
```yaml
security:
authorization:
server-configuration:
"[settings.authorization-server.jwk-set-endpoint]": /protocol/openid-connect/certs
"[settings.authorization-server.oidc-user-info-endpoint]": /protocol/openid-connect/userinfo
public-paths:
- /favicon.ico
- /actuator/**
code-flow:
permissive-redirect: true # Development only
client-registration:
my-client:
secret: "{noop}secret" # Use {bcrypt} in production
client-authentication-methods:
- client_secret_basic
authorization-grant-types:
- authorization_code
- refresh_token
redirect-uris:
- https://my-app.example.com/callback
scopes:
- openid
- profile
token-configuration:
"[settings.token.claim-mappers]":
- attributeName: aspspId
toAccessToken: true
- attributeName: consentId
toAccessToken: true
- attributeName: preferred_username
toIdToken: true
```

### Client Registration

Clients are configured in `application.yml` under `security.authorization.client-registration`:

**Example Client (Keycloak Broker):**
```yaml
keycloak-broker-client:
secret: "{noop}secret"
client-authentication-methods:
- client_secret_basic
authorization-grant-types:
- client_credentials
- authorization_code
- refresh_token
redirect-uris:
- http://localhost:8180/auth/realms/mastercard/broker/mastercard/endpoint
scopes:
- openid
- profile
```

**Example Public Client (SPA/Mobile):**
```yaml
web-client:
client-authentication-methods:
- none # Public client
authorization-grant-types:
- authorization_code
- refresh_token
redirect-uris:
- http://host.docker.internal:8080/en/select-context
scopes:
- openid
- profile
```

## Authentication Flow Details

### 1. Authorization Request

Client initiates authorization:
```
GET /oauth2/authorize?
response_type=code&
client_id=my-client&
redirect_uri=https://my-app.example.com/callback&
scope=openid profile&
state=xyz&
aspspId=420e5cff-0e2a-4156-991a-f6eeef0478cf
```

### 2. Consent Initiation

If user not authenticated:
- Server creates consent request with Mastercard
- Receives SCA redirect URL
- Redirects user to Mastercard's consent authorization page

### 3. User Authorization

User authenticates and authorizes consent at ASPSP:
- Views account information permissions
- Authorizes or denies access
- Redirected back with authorization code

### 4. Callback Processing

Authorization server receives callback:
```
GET /ai/consents/callback?
authorization=AUTH_CODE&
aspspId=420e5cff-0e2a-4156-991a-f6eeef0478cf
```

- Exchanges authorization for consent
- Retrieves consent ID
- Creates authenticated session
- Redirects to OAuth2 authorization endpoint

### 5. Token Exchange

Client exchanges authorization code for tokens:
```
POST /oauth2/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&
code=AUTHORIZATION_CODE&
redirect_uri=https://my-app.example.com/callback&
client_id=my-client&
client_secret=secret
```

Response:
```json
{
"access_token": "eyJhbGc...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "eyJhbGc...",
"id_token": "eyJhbGc...",
"scope": "openid profile"
}
```

### 6. Token Claims

**Access Token Claims:**
```json
{
"sub": "sara",
"aspspId": "420e5cff-0e2a-4156-991a-f6eeef0478cf",
"consentId": "e9d77b12-3c4a-4f2e-9c1a-8d9e7f6a5b4c",
"scope": "openid profile",
"exp": 1700000000,
"iat": 1699996400
}
```

**ID Token Claims:**
```json
{
"sub": "sara",
"preferred_username": "sara",
"aud": "my-client",
"exp": 1700000000,
"iat": 1699996400
}
```

## API Client Generation

The server generates Mastercard OpenBanking Connect API clients during build:

**Generated APIs:**
- `AiConsentsApi` - Consent creation and management
- `AiConsentsAuthorizationsApi` - Authorization exchange

**Generation Configuration:**
```xml
https://static.developer.mastercard.com/content/open-banking-connect/swagger/api-accounts-service.yaml
com.mastercard.mcob.ais.api
com.mastercard.mcob.ais.model
```

## Build and Run

### Prerequisites

- Java 17 or higher
- Maven 3.6+
- Access to Mastercard OpenBanking Connect Sandbox

### Build the Service

```bash
mvn clean install
```

### Run Locally

```bash
mvn spring-boot:run -Dspring-boot.run.profiles=sandbox
```

### Run with Docker

Build Docker image:
```bash
mvn compile jib:dockerBuild
```

Run container:
```bash
docker run -p 8081:8081 \
-e SPRING_PROFILES_ACTIVE=sandbox \
authorization-server:1.5.1
```

## Testing

### Run Unit Tests

```bash
mvn test
```

### Test Authorization Flow

1. **Start the server:**
```bash
mvn spring-boot:run -Dspring-boot.run.profiles=sandbox
```

2. **Initiate authorization:**
```bash
open "http://localhost:8081/oauth2/authorize?response_type=code&client_id=web-client&redirect_uri=http://host.docker.internal:8080/en/select-context&scope=openid%20profile&state=test123"
```

3. **Complete consent at Mastercard Sandbox**

4. **Exchange code for token:**
```bash
curl -X POST http://localhost:8081/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "code=AUTHORIZATION_CODE" \
-d "redirect_uri=http://host.docker.internal:8080/en/select-context" \
-d "client_id=web-client"
```

### Verify Token

Decode the JWT at [jwt.io](https://jwt.io) to verify claims.

## Monitoring and Operations

### Actuator Endpoints

Enable all actuator endpoints in `application-sandbox.yml`:
```yaml
management:
endpoints:
enabled-by-default: true
web:
exposure:
include: '*'
```

**Available Endpoints:**
- `/actuator/health` - Health check
- `/actuator/info` - Build information
- `/actuator/httptrace` - HTTP request traces
- `/actuator/metrics` - Application metrics
- `/actuator/loggers` - Logger configuration

### Logging

**Default Levels:**
```yaml
logging:
level:
root: INFO
com.backbase.authorization: DEBUG
org.springframework.security: DEBUG
```

## Integration with Backbase

### Token Propagation

The authorization server issues tokens with custom claims that are consumed by downstream services:

1. **Access Token** includes `aspspId` and `consentId`
2. **Integration Service** extracts claims from token
3. **Claims used in Mastercard API calls** for account information

### Example Integration Flow

```
User Browser → Authorization Server → Mastercard SCA

[Consent Created]

Access Token (with aspspId, consentId)

Backbase Platform → Integration Service → Mastercard AIS API
```

## Security Considerations

### Production Deployment

**Required Changes:**
1. **Use encrypted secrets:** Replace `{noop}` with `{bcrypt}`
2. **Disable permissive redirect:** Set `code-flow.permissive-redirect: false`
3. **Configure HTTPS:** Use TLS for all endpoints
4. **Restrict public paths:** Minimize exposed endpoints
5. **Enable CORS carefully:** Configure specific origins
6. **Use persistent storage:** Replace in-memory repositories
7. **Rotate JWK keys:** Implement key rotation strategy
8. **Set secure token lifetimes:** Balance UX and security
9. **Enable rate limiting:** Protect against abuse
10. **Monitor and audit:** Track authorization requests

### Redirect URI Security

The `AllowedRedirectUriValidator` prevents open redirect attacks:
- Validates redirect URIs against registered patterns
- Supports wildcard matching for development
- Enforces strict validation in production

### Password Encoding

Client secrets support Spring Security password encoders:
- `{noop}` - Plain text (development only)
- `{bcrypt}` - BCrypt (recommended for production)
- `{pbkdf2}` - PBKDF2
- `{scrypt}` - SCrypt
- `{sha256}` - SHA-256

## Development Notes

### Adding a New Client

1. Add client configuration to `application.yml`:
```yaml
security:
authorization:
client-registration:
my-new-client:
secret: "{bcrypt}$2a$10$..."
# ... other settings
```

2. Configure token claim mappings if needed

3. Register redirect URIs

### Adding Custom Claims

1. Update authentication to include attributes:
```java
Map attributes = new HashMap<>();
attributes.put("customClaim", value);
new AttributesAuthenticationToken(principal, attributes);
```

2. Configure claim mapper in client settings:
```yaml
token-configuration:
"[settings.token.claim-mappers]":
- attributeName: customClaim
toAccessToken: true
toIdToken: false
toUserInfo: true
```

### Customizing Consent Flow

Modify `AiConsentRedirectEntryPoint` to:
- Change consent permissions
- Adjust validity periods
- Customize callback behavior
- Add additional ASPSP logic

## Troubleshooting

### Common Issues

**Issue: "Invalid redirect URI"**
- Verify redirect URI matches registered URI exactly
- Check `code-flow.permissive-redirect` setting
- Review `AllowedRedirectUriValidator` configuration

**Issue: "Failed when fetching authorizations"**
- Verify Mastercard API credentials
- Check network connectivity
- Review proxy configuration if behind corporate firewall
- Verify ASPSP ID is correct

**Issue: "Consent expired"**
- Check `consent-validity` duration
- Verify system time synchronization
- Review token expiration settings

**Issue: "User not found"**
- Verify user mapping in ASPSP configuration
- Check consent ID returned from Mastercard
- Review `AiConsentUsersRepository` logic

### Debug Logging

Enable trace logging for troubleshooting:
```yaml
logging:
level:
com.backbase.authorization: TRACE
org.springframework.security: TRACE
org.springframework.security.oauth2: TRACE
```

## Known Limitations

- **In-memory storage** - Not suitable for production clusters
- **Single JWK key** - No key rotation implemented
- **Basic user mapping** - Simple user-to-consent association
- **No consent revocation** - Manual cleanup required
- **Sandbox only** - Configured for Mastercard sandbox environment

## Future Enhancements

- Persistent authorization storage (database)
- Dynamic client registration (RFC 7591)
- Consent revocation API
- JWK key rotation
- Enhanced user management
- Support for PSD2 SCA exemptions
- Webhook support for consent status updates
- Multi-factor authentication
- Session management UI

## Related Components

This server works in conjunction with:
- **Mastercard Integration Service** - Consumes tokens for API calls
- **Backbase Identity** - Can be integrated as identity provider
- **Keycloak** - Can broker authentication through this server

## References

- [Spring Authorization Server Documentation](https://docs.spring.io/spring-authorization-server/docs/current/reference/html/)
- [Mastercard OpenBanking Connect Documentation](https://developer.mastercard.com/open-banking-connect/documentation/)
- [OAuth 2.0 Authorization Framework](https://datatracker.ietf.org/doc/html/rfc6749)
- [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html)
- [PSD2 Regulatory Technical Standards](https://www.eba.europa.eu/regulation-and-policy/payment-services-and-electronic-money/regulatory-technical-standards-on-strong-customer-authentication-and-secure-communication-under-psd2)

## License

This is a proof-of-concept implementation for integration purposes. Do not use it in production.