OpenID Support

A little spring-boot application to facilitate authenticated use of brix:anura through an OpenID provider.

This works exactly like the CELUM login, except the resulting token is a JWT, so use the anuraJsonWebTokenVerifier in the back-end.

openid-flow

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:

    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

  • 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

    [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://<ip>:8885/login and get redirected to the OpenID server.

  • Ensure your anura setting in <celum.home>/appserver/conf/custom.properties contain

    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:

    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://<ip>:8885/anura-openid;
    }
    
    # ...
    }

    Apache2:

    <VirtualHost *:443>
    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://<ip>:8885/anura-openid
    ProxyPassReverse /anura-openid http://<ip>:8885/anura-openid
    
    # ...
    </VirtualHost>
  • Front-end: Use this snippet 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.

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<String>. 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<String>. 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.

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 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 and 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

1.2

Released: 2021-09-28

Support for attribute->endpoint mappings

1.3

Released: 2021-10-01

Support for attribute relaying