Wiki source code of OpenID Authentication with Keycloak
Version 3.1 by Vincent Massol on 2020/08/31 14:05
Show last authors
author | version | line-number | content |
---|---|---|---|
1 | {{info}} | ||
2 | The steps below assume, that you have a working Keycloak installation and the clients can connect to XWiki and Keycloak. | ||
3 | {{/info}} | ||
4 | |||
5 | Follow these steps: | ||
6 | * Find ##xwiki.authentication.authclass## in ##xwiki.cfg## and comment it out with ###-### in the beginning. | ||
7 | * Add below: ##xwiki.authentication.authclass=org.xwiki.contrib.oidc.auth.OIDCAuthServiceImpl## | ||
8 | * Save ##xwiki.cfg## | ||
9 | * Open ##xwiki.properties## and adapt the following to your settings, and add this at the end of the file (Note the ##_~_XXX_~_## parts):((( | ||
10 | {{code language='properties'}} | ||
11 | oidc.xwikiprovider=https://__YOUR-WIKI-ADDRESS__/xwiki/oidc | ||
12 | oidc.endpoint.authorization=https://__KEYCLOAK-ADDRESS__/auth/realms/__REALM__/protocol/openid-connect/auth | ||
13 | oidc.endpoint.token=https://__KEYCLOAK-ADDRESS__/auth/realms/__REALM__/protocol/openid-connect/token | ||
14 | oidc.endpoint.userinfo=https://__KEYCLOAK-ADDRESS__/auth/realms/__REALM__/protocol/openid-connect/userinfo | ||
15 | oidc.scope=openid,profile,email,address | ||
16 | oidc.endpoint.userinfo.method=GET | ||
17 | oidc.user.nameFormater=${oidc.user.preferredUsername._clean._lowerCase} | ||
18 | oidc.user.subjectFormater=${oidc.user.subject} | ||
19 | # oidc.groups.claim=xwiki_groups | ||
20 | # oidc.groups.mapping=MyXWikiGroup=my-oidc-group | ||
21 | # oidc.groups.mapping=MyXWikiGroup2=my-oidc-group2 | ||
22 | # oidc.groups.mapping=MyXWikiGroup2=my-oidc-group3 | ||
23 | # oidc.groups.allowed= | ||
24 | # oidc.groups.forbidden= | ||
25 | oidc.userinfoclaims=xwiki_user_accessibility,xwiki_user_company,xwiki_user_displayHiddenDocuments,xwiki_user_editor,xwiki_user_usertype | ||
26 | # oidc.userinforefreshrate=600000 | ||
27 | oidc.clientid=__KEYCLOAK-CLIENT-ID__ | ||
28 | oidc.secret=__KEYCLOAK-CLIENT-SECRET__ | ||
29 | oidc.endpoint.token.auth_method=client_secret_basic | ||
30 | oidc.skipped=false | ||
31 | {{/code}} | ||
32 | |||
33 | {{info}} | ||
34 | See [[futher configuration possibilites>>||anchor="Hxwiki.properties"]]. | ||
35 | {{/info}} | ||
36 | ))) | ||
37 | * Adapt the following to your settings and import it to Keycloak (Again: Note the ##_~_XXX_~_## parts):((( | ||
38 | {{code language='json'}} | ||
39 | { | ||
40 | "clientId": "__CLIENT-ID__", | ||
41 | "name": "__CLIENT-NAME__", | ||
42 | "rootUrl": "https://__YOUR-WIKI-URL__", | ||
43 | "adminUrl": "https://__YOUR-WIKI-URL__", | ||
44 | "baseUrl": "https://__YOUR-WIKI-URL__", | ||
45 | "surrogateAuthRequired": false, | ||
46 | "enabled": true, | ||
47 | "alwaysDisplayInConsole": false, | ||
48 | "clientAuthenticatorType": "client-secret", | ||
49 | "redirectUris": [ | ||
50 | "https://__YOUR-WIKI-URL__/*" | ||
51 | ], | ||
52 | "webOrigins": [ | ||
53 | "https://__YOUR-WIKI-URL__" | ||
54 | ], | ||
55 | "notBefore": 0, | ||
56 | "bearerOnly": false, | ||
57 | "consentRequired": false, | ||
58 | "standardFlowEnabled": true, | ||
59 | "implicitFlowEnabled": true, | ||
60 | "directAccessGrantsEnabled": true, | ||
61 | "serviceAccountsEnabled": true, | ||
62 | "authorizationServicesEnabled": true, | ||
63 | "publicClient": false, | ||
64 | "frontchannelLogout": false, | ||
65 | "protocol": "openid-connect", | ||
66 | "attributes": { | ||
67 | "saml.assertion.signature": "false", | ||
68 | "saml.force.post.binding": "false", | ||
69 | "saml.multivalued.roles": "false", | ||
70 | "saml.encrypt": "false", | ||
71 | "saml.server.signature": "false", | ||
72 | "saml.server.signature.keyinfo.ext": "false", | ||
73 | "exclude.session.state.from.auth.response": "false", | ||
74 | "saml_force_name_id_format": "false", | ||
75 | "saml.client.signature": "false", | ||
76 | "tls.client.certificate.bound.access.tokens": "false", | ||
77 | "saml.authnstatement": "false", | ||
78 | "display.on.consent.screen": "false", | ||
79 | "saml.onetimeuse.condition": "false" | ||
80 | }, | ||
81 | "authenticationFlowBindingOverrides": {}, | ||
82 | "fullScopeAllowed": false, | ||
83 | "nodeReRegistrationTimeout": -1, | ||
84 | "protocolMappers": [{ | ||
85 | "name": "Client Host", | ||
86 | "protocol": "openid-connect", | ||
87 | "protocolMapper": "oidc-usersessionmodel-note-mapper", | ||
88 | "consentRequired": false, | ||
89 | "config": { | ||
90 | "user.session.note": "clientHost", | ||
91 | "id.token.claim": "true", | ||
92 | "access.token.claim": "true", | ||
93 | "claim.name": "clientHost", | ||
94 | "jsonType.label": "String" | ||
95 | } | ||
96 | }, | ||
97 | { | ||
98 | "name": "Client IP Address", | ||
99 | "protocol": "openid-connect", | ||
100 | "protocolMapper": "oidc-usersessionmodel-note-mapper", | ||
101 | "consentRequired": false, | ||
102 | "config": { | ||
103 | "user.session.note": "clientAddress", | ||
104 | "id.token.claim": "true", | ||
105 | "access.token.claim": "true", | ||
106 | "claim.name": "clientAddress", | ||
107 | "jsonType.label": "String" | ||
108 | } | ||
109 | }, | ||
110 | { | ||
111 | "name": "address", | ||
112 | "protocol": "openid-connect", | ||
113 | "protocolMapper": "oidc-address-mapper", | ||
114 | "consentRequired": false, | ||
115 | "config": { | ||
116 | "user.attribute.formatted": "formatted", | ||
117 | "user.attribute.country": "country", | ||
118 | "user.attribute.postal_code": "postal_code", | ||
119 | "userinfo.token.claim": "true", | ||
120 | "user.attribute.street": "street", | ||
121 | "id.token.claim": "true", | ||
122 | "user.attribute.region": "region", | ||
123 | "access.token.claim": "true", | ||
124 | "user.attribute.locality": "locality" | ||
125 | } | ||
126 | }, | ||
127 | { | ||
128 | "name": "Client ID", | ||
129 | "protocol": "openid-connect", | ||
130 | "protocolMapper": "oidc-usersessionmodel-note-mapper", | ||
131 | "consentRequired": false, | ||
132 | "config": { | ||
133 | "user.session.note": "clientId", | ||
134 | "id.token.claim": "true", | ||
135 | "access.token.claim": "true", | ||
136 | "claim.name": "clientId", | ||
137 | "jsonType.label": "String" | ||
138 | } | ||
139 | } | ||
140 | ], | ||
141 | "defaultClientScopes": [ | ||
142 | "web-origins", | ||
143 | "role_list", | ||
144 | "roles", | ||
145 | "profile", | ||
146 | "email" | ||
147 | ], | ||
148 | "optionalClientScopes": [ | ||
149 | "address", | ||
150 | "phone", | ||
151 | "offline_access", | ||
152 | "microprofile-jwt" | ||
153 | ], | ||
154 | "access": { | ||
155 | "view": true, | ||
156 | "configure": true, | ||
157 | "manage": true | ||
158 | } | ||
159 | } | ||
160 | {{/code}} | ||
161 | ))) | ||
162 | |||
163 | {{warning}} | ||
164 | After importing this to Keycloak, you have to generate a new Client-Secret and put it into ##xwiki.properties## under ##oidc.secret=_~_KEYCLOAK-CLIENT-SECRET_~_##. | ||
165 | Aim is: In the end, Client-ID and Client-Secret have to match on Keycloak and in ##xwiki.properties##. | ||
166 | {{/warning}} |