OpenID (OAuth2) implementácia
Backend
Konfigurácia
Verzia Spring security, na ktorej NAE dependuje, poskytuje oauth2 autorizáciu prostredníctvom JWT tokenov. Default-nú security konfiguráciu s týmto nastavením (SecurityConfigurationSSO
, OAuthUserServiceConfiguration
) je možné aktivovať úpravou application.properties:
nae.oauth.enabled=true
Do properties je následne potrebné špecifikovať cesty na preddefinované endpoint-y autorizačného serveru. Príklad pre Keycloak IDM (ktorý beží pod localhost:8080):
security.oauth2.resource.jwk.key-set-uri=http://localhost:8080/auth/realms/Test/protocol/openid-connect/certs
security.oauth2.resource.user-info-uri=http://localhost:8080/auth/realms/Test/protocol/openid-connect/userinfo
Keď client (napr. frontend) vyžiada akýkoľvek resource z backend-u, autorizuje sa prostredníctvom access_token-u, ktorý obdržal z autorizačného serveru. Tento token do authorization header-u vkladá ako Bearer token. Backend (Spring security) používateľa overí a dotiahne jeho údaje z autorizačného serveru. Backend následne použitím implementácie triedy IOauthUserMapper
z údajov vyskladá používateľa (Authentication → LoggedUser).
Defaultne existujú dve implementácie IOauthUserMapper
; OAuthUserMapper
pre remote user base a ServiceUserMapper
pre vlastný user base.
OAuthUserMapper
je inicializovaný v prípade, že nasledovná property je aktivovaná. Interne používa implementáciu rozhrania IOAuthUserService
na dohľadanie/vytvorenie nového používateľa (OAuthUser
).
nae.oauth.remote-user-base=true
Táto implementácia mapper-u požaduje v properties špecifikovať kľúče mapovaných údajov:
nae.oauth.mapper.name=given_name
nae.oauth.mapper.surname=family_name
nae.oauth.mapper.email=email
nae.oauth.mapper.id=sub
Spolu s ním je inicializovaná aj service OAuthUserService
, ktorá je závislá na IRemoteUserResourceService
a IRemoteGroupResourceService
. Implementácie týchto dvoch rozhraní je potrebné poskytnúť buď vlastné, alebo použiť defaultné, ktoré sú špecifické pre Keycloak.
Ak je autorizačný server Keycloak, stačí pridať nasledovné properties:
nae.oauth.keycloak=true
security.oauth2.client.realm=Test
security.oauth2.client.serverUrl=http://localhost:8080/auth
V tomto prípade sú použité implementácie KeycloakUserResourceService
a KeycloakGroupResourceService
, ktoré cez Keycloak Admin API pristupujú k používateľom. Autorizácia backend-u voči Keycloak-u na doťahovanie informácií o používateľoch pre potreby NAE je defaultne realizovaná cez clientId a clientSecret (KeycloakConfiguration
).
security.oauth2.client.clientId=test-client
security.oauth2.client.clientSecret=abcedfgh-abcd-1234-4567-12345555d338
User management
Implementácia OAuthUserService
s používateľmi narába bez potreby mať ich od začiatku naimportovaných v databáze. Používatelia sú cez IRemoteUserResourceService
dynamicky doťahovaní poďla potreby. Pri prvom prihlásení (OAuthUserMapper
) alebo keď je používateľovi v NAE prvýkrát pridelená autorita alebo procesná rola, je o ňom vytvorený minimálny záznam v MongoDB, ktorý obsahuje autority, procesné roly, skupiny, lokálne ID a ID v originálnej user base. OAuthUser
a OAuthLoggedUser
objekty sa interne reprezentujú (cez stringId) svojim ID v originálnej user base.
Metódy OAuthUserService
, ktorých návratová hodnota je typu zoznam/stránka používateľov, vracajú používateľov namapovaných na záznamy v DB (teda s autoritami, procesnými rolami …) a taktiež používateľov, ktorí sa v DB ešte nenachádzajú (bez autorít, rolí, taktiež nemajú internú property _id).
Upravovanie údajov používateľov nájdených prostredníctvom ID a ich následné uloženie cez save metódu IUserService
je vhodné, pokiaľ používateľ bol dohľadaný cez metódu resolveById
. Táto metóda v OAuthUserService
používateľa vytvorí v DB, ak dosiaľ neexistuje, a pridelí mu default autoritu, skupinu, atp. Metóda findById
v tejto service používateľa môže vrátiť aj keď sa ten v MongoDB stále nenachádza a teda nebude mať default nastavené údaje.
Záznamy o anonymných používateľoch a systémovom používateľovi sú naďalej ukladané v MongoDB.
Frontend
"auth": {
"address": "http://localhost:8080/api/",
"authentication": "SSO",
"sso": {
"refreshUrl": "https://idm.netgrif.com:8443/auth/realms/TEST/protocol/openid-connect/token",
"login": "https://idm.netgrif.com:8443/auth/realms/TEST/protocol/openid-connect/auth",
"logout": "https://idm.netgrif.com:8443/auth/realms/TEST/protocol/openid-connect/logout",
"automaticLogin": true,
"refreshConfig": {
"clientID": "frontend",
"clientSecret": "TOKEN"
}
},
"endpoints": {
"login": "auth/login",
"logout": "auth/logout",
"signup": "auth/signup",
"verification": "auth/verify",
"verify": "auth/token/verify",
"invite": "auth/invite",
"reset": "auth/reset",
"recover": "/auth/recover"
},
"sessionBearer": "Authorization",
"jwtBearer": "X-Jwt-Token"
},