A little spring-boot application to facilitate authenticated use of brix:anura through an [OpenID](https://openid.net) provider. This works exactly like the [CELUM login](/anura/backend/celum-token-verifier), except the resulting token is a JWT, so use the [anuraJsonWebTokenVerifier](/anura/backend#anura-1-token-verifier) in the back-end. ![openid-flow](openid_flow.png) [MINITOC] ## Setup * Create a folder somewhere, e.g. in `/opt/celum/server/anura`, and place the `anura-openid.jar` inside. * Add a configuration file `application.properties` alongside said jar (with all the usual spring-boot properties) Any `spring.security.oauth2.client` is supported, this example uses `keycloak`: ```ini server.port=8885 # required when running behind a reverse proxy: server.forward-headers-strategy=native server.servlet.context-path=/anura-openid logging.file.name=anura-openid.log logging.level.root=info anura.openid.jwt-secret=*****at-least-256-bits****** spring.security.oauth2.client.registration.keycloak.client-id=******* spring.security.oauth2.client.registration.keycloak.client-secret=************ spring.security.oauth2.client.registration.keycloak.client-name=keycloak spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code spring.security.oauth2.client.registration.keycloak.redirectUriTemplate=https://celum.server/anura-openid/oauth2/callback/{registrationId} spring.security.oauth2.client.registration.keycloak.scope=openid, profile, email spring.security.oauth2.client.provider.keycloak.authorization-uri=https://keycloak.server/auth/realms/master/protocol/openid-connect/auth spring.security.oauth2.client.provider.keycloak.token-uri=https://keycloak.server/auth/realms/master/protocol/openid-connect/token spring.security.oauth2.client.provider.keycloak.user-info-uri=https://keycloak.server/auth/realms/master/protocol/openid-connect/userinfo spring.security.oauth2.client.provider.keycloak.jwk-set-uri=https://keycloak.server/auth/realms/master/protocol/openid-connect/certs spring.security.oauth2.client.provider.keycloak.issuer-uri=https://keycloak.server/auth/realms/master spring.security.oauth2.client.provider.keycloak.user-name-attribute=preferred_username ``` > > > > `anura.openid.jwt-secret` must match your [anura.1.jwtSecretKey](https://docs.brix.ch/anura/backend#anura-1-token-verifier) * Test if your configuration is valid by running `java -jar anura-openid.jar` * Register the app as a service, e.g. in `/etc/systemd/system/anura-openid.service` ```ini [Unit] Description=anura-openid After=syslog.target network.target [Service] User=celum WorkingDirectory=/opt/celum/server/anura ExecStart=/usr/bin/java -jar /opt/celum/server/anura/anura-openid.jar SuccessExitStatus=143 [Install] WantedBy=multi-user.target ``` * Reload `systemctl daemon-reload` and start the service `systemctl start anura-openid` > > > > > > you probably want this to autostart: `systemctl enable anura-openid` * You should now be able to visit `http://:8885/login` and get redirected to the OpenID server. * Ensure your anura setting in `/appserver/conf/custom.properties` contain ```ini anura.1.tokenVerifier=anuraJsonWebTokenVerifier anura.1.jwtSecretKey=*****at-least-256-bits****** # optional: anura.1.downloadHandler=anuraJsonWebTokenDownloader ``` * Configure a nice URL for this service, e.g. in the existing appserver directive: nginx: ```json server { listen 443 ssl; server_name celum.server; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host:443; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # pass https://celum.server/anura-openid to service listening on :8885 location /anura-openid { proxy_pass http://:8885/anura-openid; } # ... } ``` Apache2: ```ini ServerName celum.server SSLProxyEngine on ProxyPreserveHost On RequestHeader set X-Forwarded-Port "443" RequestHeader set X-Forwarded-Proto "https" RemoteIPHeader X-Forwarded-For ProxyPass /anura-openid http://:8885/anura-openid ProxyPassReverse /anura-openid http://:8885/anura-openid # ... ``` * Front-end: Use [this snippet](/anura/frontend/snippets#authenticating-against-celum) and replace `anuraLoginToken` with the `anura-openid` from above (or substitute the URL when running somewhere else) ## Properties ##### anura.openid.jwt-secret > type: String, **required: yes**, default: - The JWT secret key you want to use. Must be at least 256bits and must match [anura.1.jwtSecretKey](https://docs.brix.ch/anura/backend#anura-1-token-verifier). ##### anura.openid.expire-millis > type: long, required: no, default: 43200000 How long the created JWT should last in milliseconds, default is 12h. ##### anura.openid.endpoint-claim > type: String, required: no, default: - Which OpenID claim to use in order to determine the `endpoint` parameter. Supported claims types: `String` and `List`. E.g. `country`. ##### anura.openid.endpoint-attribute > type: String, required: no, default: - Which OpenID attribute to use in order to determine the `endpoint` parameter. This is an alternative to the `claim` properties from above - **claims will be considered first**. Supported attribute types: `String` and `List`. E.g. `country`. ##### anura.openid.endpoint-mapping > type: List of string:pairs (comma separated), required: no, default: - When using `anura.openid.endpoint-claim` (or `endpoint-attribute`), use this map to "translate" the incoming claim to an actual endpoint. E.g. ```ini anura.openid.endpoint-claim=country anura.openid.endpoint-mapping=DE:endpoint1,AT:endpoint2,CH:endpoint3 ``` ... would result in `...&endpoint=endpiont3` if the user had the claim `country: CH`. Note that for multiple matches, the first one will be used. ##### anura.openid.relay-attributes > type: List of string (comma separated), required: no, default: -, since: 1.3 Which user attribute(s) to relay as an [outbound](#outbound) query parameter. The parameter names will be the same as the attribute names. ## Parameters ### Inbound ##### /login?to= > type: URL, **required: yes**, default: - Where to redirect the user back to after he successfully logs in with OpenID, e.g. `login?to=https://anura.server/some-page.html` ### Outbound ##### token > type: JWT, **guaranteed: yes**, default: - The JWT token that was created for the user after successfully authenticating via OpenID. This parameter will be added to the inbound **to** URL, e.g. `https://anura.server/some-page.html?token={JWT}` ##### endpoint > type: String, guaranteed: no, deafult: - The endpoint that resulted from evaluating the [endpoint-claim](#anura-openid-endpoint-claim) and [claim-mapping](#anura-openid-claim-mapping) settings. This parameter may be added to the inbound **to** URL, e.g. `https://anura.server/some-page.html?token={JWT}&endpoint=some-endpoint` ## Compatibility * Anura: 2.9 and above (through `anuraJsonWebTokenVerifier`) * OpenID: Tested with Keycloak 10.0 ## Release Notes #### 1.0 > Released: 2021-09-02 Initial release #### 1.1 > Released: 2021-09-03 Support for [claim->endpoint mappings](#anura-openid-endpoint-claim) #### 1.2 > Released: 2021-09-28 Support for [attribute->endpoint mappings](#anura-openid-endpoint-attribute) #### 1.3 > Released: 2021-10-01 Support for [attribute relaying](#anura-openid-relay-attributes)