OAuth2 and SmartWeb Proxy Configuration
There are two OAuth2-related deployments in the SmartWeb platform:
OAuth2 token endpoint — a REST endpoint embedded in the main SmartWeb process that exchanges D2000 credentials for an OAuth2 access / refresh token from an upstream identity provider (Keycloak, Azure AD, …). Useful for native applications that already authenticate against D2000 but need to call upstream APIs protected by OAuth2.
SmartWeb Proxy — a separate Spring Cloud Gateway process deployed in front of the main SmartWeb. It performs the OAuth2 Authorization Code flow with the IdP on behalf of the browser, keeps the OAuth2 tokens on the server side in an encrypted cookie and injects a bearer token into every forwarded request. The browser never sees the OAuth2 tokens.
[!NOTE]
The main SmartWeb process does not validate incoming OAuth2 JWT bearer tokens on API requests (/api/rest/**, /api/odata/**, /api/open/**, gRPC) — server-to-server clients authenticate with an API key (X-API-Key) or HTTP Basic authentication. Logging a browser user in through an external identity provider (OIDC/IAM) is handled by the AUTH_OIDC_LOCALLY mode. Both are described in Configuration of Authentication.
OAuth2 token endpoint
Exposure path: /api/oauth2 (secured the same way as the server-to-server REST API — API key, JWT or Basic auth).
Method | Path | Description |
|---|---|---|
|
| Exchange D2000 credentials for an upstream OAuth2 token |
Request
{
"username": "operator1",
"password": "secret",
"realm": "my-keycloak-realm",
"scope": "openid profile"
}Successful response
The full token response from the upstream IdP is forwarded as is (RFC 6749):
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "abc123...",
"scope": "openid profile"
}Error response
{
"error": "invalid_grant",
"error_description": "Invalid D2000 credentials"
}Configuration
smartweb:
authentication:
oauth2:
realms:
- name: "my-keycloak-realm"
tokenUrl: "https://keycloak.example.com/realms/my-realm/protocol/openid-connect/token"
clientId: "smartweb-client"
clientSecret: "client-secret-value"
scope: "openid profile"
authMode: D2000 # D2000 | EXTERNAL
- name: "azure-ad"
tokenUrl: "https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token"
clientId: "app-client-id"
clientSecret: "app-secret"
scope: "https://graph.microsoft.com/.default"
authMode: D2000Property | Description |
|---|---|
| Identifier of the realm that the client sends in the |
| OAuth2 token endpoint of the upstream IdP |
| Confidential client credentials registered in the IdP |
| Space-separated list of OAuth2 scopes |
|
|
SmartWeb Proxy
SmartWeb Proxy is a standalone Spring Boot application packaged as smartweb-proxy.jar. It runs in front of the main SmartWeb instance and acts as a confidential OAuth2 client (token-mediating backend). The browser sessions carry only an encrypted cookie holding the OAuth2 refresh context; the access and refresh tokens never leave the server.
Browser → SmartWeb Proxy → SmartWeb (web-jar) → D2000
│
└── OAuth2 Authorization Code + Refresh flows with the IdPStarting the proxy
java -jar smartweb-proxy.jar \
--spring.config.location=file:/opt/smartweb-proxy/config/application.yamlFull configuration example (/opt/smartweb-proxy/config/application.yaml)
# Context root of the proxy (also the base path for cookies and redirects)
spring.webflux.base-path: /edc-mobile
# Truststore for outbound TLS connections to the IdP and the backend SmartWeb
javax.net.ssl.trustStore: ./config/truststore.jks
smartweb:
proxy:
auth:
# Cookie-based authentication for the token-mediating backend exposed at
# {spring.webflux.base-path}/auth/token
token-mediating-backend:
enabled: true
persistence-cookie:
name: REMEMBER_ME_COOKIE
domain: localhost
path: "${spring.webflux.base-path:}/login"
ttl: 30D
secure: false
same-site: Strict
# AES-GCM symmetric encryption key for the refresh-context cookie (hex, 32 bytes)
encryption-secret: 6698ccc5a0469f58ff1e12de02eff22792968678dfca597e709fb34bd67d81ce
encryption-salt: f40173ec5eed0e0346621f32a3a774dc
auth-success-redirect-uri: "${spring.webflux.base-path:}/index.html"
client-registration-id: edc-web-mobile-client
spring:
application:
name: smartweb-proxy
security:
oauth2:
# OAuth2 resource server for the /api/** endpoints
resourceserver:
jwt:
issuer-uri: https://iam-test-edc.okte.sk/auth/realms/edc-external
# OAuth2 client for the token-mediating-backend endpoint
client:
registration:
edc-web-mobile-client:
provider: edc-web-mobile-provider
client-id: edc-core-ui
client-secret: V4gwRiLcv4RP9zj2BJ1oAzMLS3kFhpMu
authorization-grant-type: authorization_code
# For long-lived sessions add "offline_access"
scope: openid,profile,offline_access
provider:
edc-web-mobile-provider:
issuer-uri: https://iam-test-edc.okte.sk/auth/realms/edc-external
cloud:
# Where to send forwarded requests. Multiple instances enable round-robin load balancing.
discovery:
client:
simple:
instances:
smartweb-frontend-service:
- uri: http://localhost:5173
smartweb-backend-service:
- uri: http://localhost:80/edccore
# Spring Cloud Gateway routes
gateway:
server:
webflux:
routes:
- id: api
uri: lb://smartweb-backend-service
predicates:
- Path=/api/**
filters:
- UsernameHeader # adds X-SmartWeb-User from the OAuth2 principal
- RemoveRequestHeader=Authorization
- SetRequestHeader=X-Api-Key, <smartweb-api-key>
- RewritePath=/edc-mobile/?(?<segment>.*), /edccore/$\{segment}
- id: swagger
uri: lb://smartweb-backend-service/
predicates:
- Path=/swagger/**
filters:
- RewritePath=/edc-mobile/?(?<segment>.*), /edccore/$\{segment}
- id: resources
uri: lb://smartweb-frontend-service/
predicates:
- Path=/**
metrics:
enabled: true
loadbalancer:
eager-load:
clients:
- smartweb-backend-service
- smartweb-frontend-service
health-check:
enabled: false
smartweb-backend-service:
- path: /do.healthcheck?format=simple
interval: 5s
refetch-instances: true
smartweb-frontend-service:
- path: /
interval: 5s
refetch-instances: trueKey properties
Property | Description |
|---|---|
| Context root under which the proxy serves all paths (login, gateway routes, cookies) |
| Truststore for outbound HTTPS to the IdP and the backend SmartWeb |
| Hex 32-byte AES-GCM key for encrypting the refresh-context cookie |
| Name of the Spring Security OAuth2 client registration that drives the OAuth2 flow |
| OAuth2 client credentials (client ID/secret, grant type, scopes) |
| Discovery URL of the IdP (automatically discovers |
| Gateway routes — forward to the backend SmartWeb, the frontend service, etc. The |
| Static service registry — for production multi-instance deployments replace it with a real discovery server |
[!NOTE]
The proxy is a standalone process separate from the main smartweb.jar. It must be deployed and operated independently — typically on a different host or in a different container. The backend SmartWeb must trust the proxy: define an API key that the gateway injects via the SetRequestHeader=X-Api-Key, ... filter (see Configuration of Authentication).