SSO integration with XWIKI using OIDC setup

Is there a specific redirect uri that is used when configuring SSO with Xwiki? I’m using an OIDC setup. If so, where in the xwiki.cfg or xwki.properties file should it be entered?

hi @ellis.amosu,

welcome to xwiki.

here are my steps i took, to enable OIDC-Login:

  1. Read https://extensions.xwiki.org/xwiki/bin/view/Extension/OpenID%20Connect/OpenID%20Connect%20Authenticator/ and install the extension

  2. find xwiki.authentication.authclass in xwiki.cfg and comment it out. add below:
    xwiki.authentication.authclass=org.xwiki.contrib.oidc.auth.OIDCAuthServiceImpl

  3. Save xwiki.cfg and open xwiki.properties

  4. Adopt to your settings and add this at the end of the file:

    oidc.xwikiprovider=https://YOUR-WIKI-ADDRESS/xwiki/oidc
    oidc.endpoint.authorization=https://KEYCLOAK-ADDRESS/auth/realms/REALM/protocol/openid-connect/auth
    oidc.endpoint.token=https://KEYCLOAK-ADDRESS/auth/realms/REALM/protocol/openid-connect/token
    oidc.endpoint.userinfo=https://KEYCLOAK-ADDRESS/auth/realms/REALM/protocol/openid-connect/userinfo
    oidc.scope=openid,profile,email,address
    oidc.endpoint.userinfo.method=GET
    oidc.user.nameFormater=${oidc.user.preferredUsername._clean._lowerCase}
    oidc.user.subjectFormater=${oidc.user.subject}
    # oidc.groups.claim=xwiki_groups
    # oidc.groups.mapping=MyXWikiGroup=my-oidc-group
    # oidc.groups.mapping=MyXWikiGroup2=my-oidc-group2
    # oidc.groups.mapping=MyXWikiGroup2=my-oidc-group3
    # oidc.groups.allowed=
    # oidc.groups.forbidden=
    oidc.userinfoclaims=xwiki_user_accessibility,xwiki_user_company,xwiki_user_displayHiddenDocuments,xwiki_user_editor,xwiki_user_usertype
    # oidc.userinforefreshrate=600000
    oidc.clientid=KEYCLOAK-CLIENT-ID
    oidc.secret=KEYCLOAK-CLIENT-SECRET
    oidc.endpoint.token.auth_method=client_secret_basic
    oidc.skipped=false

You see, i did this with Keaylcoak. You have to adopt the settings to your IDP.

  1. Adopt this and import it to keycloak:
   {
        "clientId": "CLIENT-ID",
        "name": "CLIENT-NAME",
        "rootUrl": "https://YOUR-WIKI-URL",
        "adminUrl": "https://YOUR-WIKI-URL",
        "baseUrl": "https://YOUR-WIKI-URL",
        "surrogateAuthRequired": false,
        "enabled": true,
        "alwaysDisplayInConsole": false,
        "clientAuthenticatorType": "client-secret",
        "redirectUris": [
            "https://YOUR-WIKI-URL/*"
        ],
        "webOrigins": [
            "https://YOUR-WIKI-URL"
        ],
        "notBefore": 0,
        "bearerOnly": false,
        "consentRequired": false,
        "standardFlowEnabled": true,
        "implicitFlowEnabled": true,
        "directAccessGrantsEnabled": true,
        "serviceAccountsEnabled": true,
        "authorizationServicesEnabled": true,
        "publicClient": false,
        "frontchannelLogout": false,
        "protocol": "openid-connect",
        "attributes": {
            "saml.assertion.signature": "false",
            "saml.force.post.binding": "false",
            "saml.multivalued.roles": "false",
            "saml.encrypt": "false",
            "saml.server.signature": "false",
            "saml.server.signature.keyinfo.ext": "false",
            "exclude.session.state.from.auth.response": "false",
            "saml_force_name_id_format": "false",
            "saml.client.signature": "false",
            "tls.client.certificate.bound.access.tokens": "false",
            "saml.authnstatement": "false",
            "display.on.consent.screen": "false",
            "saml.onetimeuse.condition": "false"
        },
        "authenticationFlowBindingOverrides": {},
        "fullScopeAllowed": false,
        "nodeReRegistrationTimeout": -1,
        "protocolMappers": [
            {
                "name": "Client Host",
                "protocol": "openid-connect",
                "protocolMapper": "oidc-usersessionmodel-note-mapper",
                "consentRequired": false,
                "config": {
                    "user.session.note": "clientHost",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "clientHost",
                    "jsonType.label": "String"
                }
            },
            {
                "name": "Client IP Address",
                "protocol": "openid-connect",
                "protocolMapper": "oidc-usersessionmodel-note-mapper",
                "consentRequired": false,
                "config": {
                    "user.session.note": "clientAddress",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "clientAddress",
                    "jsonType.label": "String"
                }
            },
            {
                "name": "address",
                "protocol": "openid-connect",
                "protocolMapper": "oidc-address-mapper",
                "consentRequired": false,
                "config": {
                    "user.attribute.formatted": "formatted",
                    "user.attribute.country": "country",
                    "user.attribute.postal_code": "postal_code",
                    "userinfo.token.claim": "true",
                    "user.attribute.street": "street",
                    "id.token.claim": "true",
                    "user.attribute.region": "region",
                    "access.token.claim": "true",
                    "user.attribute.locality": "locality"
                }
            },
            {
                "name": "Client ID",
                "protocol": "openid-connect",
                "protocolMapper": "oidc-usersessionmodel-note-mapper",
                "consentRequired": false,
                "config": {
                    "user.session.note": "clientId",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "clientId",
                    "jsonType.label": "String"
                }
            }
        ],
        "defaultClientScopes": [
            "web-origins",
            "role_list",
            "roles",
            "profile",
            "email"
        ],
        "optionalClientScopes": [
            "address",
            "phone",
            "offline_access",
            "microprofile-jwt"
        ],
        "access": {
            "view": true,
            "configure": true,
            "manage": true
        }
    }

After importing this to Keycloak you have to generate a new Client-Secret and put it into xwiki.properties.

Hope this helps.

@jwielsch Great instructions. I wonder if it wouldn’t be goods to put them on xwiki.org. Maybe in a section on https://extensions.xwiki.org/xwiki/bin/view/Extension/OpenID%20Connect/OpenID%20Connect%20Authenticator/ ? WDYT?

Thanks!

Oh, I did not knew I could contribute on the documentation like this. Sure - I can add that.

Or here: https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Authentication/ with link to the application?

It’s a wiki :slight_smile:

Thanks!

I think it’s better to have the tutorial on https://extensions.xwiki.org/xwiki/bin/view/Extension/OpenID%20Connect/OpenID%20Connect%20Authenticator/.

Then we could create an OIDC section on https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Authentication/ and link to the OIDC extension.

WDYT?

1 Like

I’m doing this part now.

Done

Sure. Sounds good.

What the… That was fast :slight_smile:

I have a documentation for kerberos, too with some changes to the one from https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Authentication/.

I’ll add that one later, when i have the time.

1 Like

@jwielsch Thanks for the keycloak info!
If you were able to setup group sync in keycloak/xwiki, would you mind to share your knowledge about that ?

Hi @jsalatiel. Sure, no problem - but it’ll take some time to write it down and I am heavily loaded with projects and have no time this weekend. but i will add it to the documentation.

Documentation added: https://extensions.xwiki.org/xwiki/bin/view/Extension/OpenID%20Connect/OpenID%20Connect%20Authenticator/OpenID%20Authentication%20with%20Keycloak/

1 Like

@jsalatiel

Just for the record: I did not forget your request. I could not write it down as I am very busy at the moment. Sorry.

Thanks a lot @jwielsch.

I’ve rewritten it a bit to follow the xwiki documentations style (https://dev.xwiki.org/xwiki/bin/view/Community/DocGuide). See https://extensions.xwiki.org/xwiki/bin/view/Extension/OpenID%20Connect/OpenID%20Connect%20Authenticator/OpenID%20Authentication%20with%20Keycloak/?viewer=changes&rev1=1.2&rev2=4.1&

Thanks!

1 Like

@jsalatiel

hi, I added a little step by step documentation on https://extensions.xwiki.org/xwiki/bin/view/Extension/OpenID%20Connect/OpenID%20Connect%20Authenticator/OpenID%20Authentication%20with%20Keycloak/Keycloak%20Group-Mapping/

Please comment on the page, if something is not working after you followed the steps to improve the article.

@jwielsch I really love it that you’re contributing documentation for xwiki.org! This is awesome :slight_smile:

I’ve just noticed the new https://extensions.xwiki.org/xwiki/bin/view/Extension/OpenID%20Connect/OpenID%20Connect%20Authenticator/OpenID%20Authentication%20with%20Keycloak/Keycloak%20Group-Mapping/ :slight_smile:

One small detail: we have some guidelines for content written on xwiki.org at https://dev.xwiki.org/xwiki/bin/view/Community/DocGuide

For example I see you added screenshots that are very large and we have some solution/recommendation for this. See https://dev.xwiki.org/xwiki/bin/view/Community/DocGuide#HScreenshots2FImages Do you think you could apply this (and check the other guidelines when you have time?)?

Thanks a lot!
Keep going

There’s also https://dev.xwiki.org/xwiki/bin/view/Community/DocGuide#HListItems to check that I see is not correct on https://extensions.xwiki.org/xwiki/bin/view/Extension/OpenID%20Connect/OpenID%20Connect%20Authenticator/OpenID%20Authentication%20with%20Keycloak/Keycloak%20Group-Mapping/

Thanks

Sure! Sorry that it is not right from the beginning. i will be happy to adapt it.
But it’s not that easy for me because, at least for me, only the XWiki syntax editor is available. I write it all down in my xWiki and then copy it over.