This guide demonstrates how to integrate Keycloak with GraphXR using multiple authentication methods:
- OpenID Connect (OAuth2) - Standard OAuth2 authentication flow
- SAML - Enterprise SAML integration
- iframe Authentication - Embedded authentication for iframe scenarios
- Prerequisites
- 1. User Management
- 2. OpenID Connect Integration
- 3. SAML Integration
- 4. iframe Authentication
- 5. Testing the UserInfo API
- Docker installed and running
- Keycloak v26.2.0
- GraphXR server instance
- Node.js and Yarn (for iframe demo)
-
Start Keycloak:
bash ./run.sh
-
Access Keycloak Admin Console:
- URL: http://localhost:8080
- Default credentials:
admin/admin
-
Import Pre-configured Clients (Optional):
- Import
GraphXR-iframe-demo.jsonin Keycloak under "Clients" section - Import
GraphXR-OpenID.jsonin Keycloak under "Clients" section
- Import
Note: The
run.shscript will start Keycloak in a Docker container with H2 database persistence.
-
Navigate to the Keycloak Users page:
-
Click "Create new user" and add the following test users:
Email Password First Name Last Name demo@demo.com demo@demo.com Demo User example@example.com example@example.com Example User -
Important Configuration Steps:
- Set "Email verified" to ON
- Under the "Credentials" tab, set the password
- Disable "Temporary" to avoid forcing password change on first login
Tip: You can create additional users as needed for testing different scenarios.
-
Navigate to Client Creation:
-
Configure Basic Settings:
Client Type: OpenID Connect Client ID: GraphXR-OpenID Name: GraphXR OpenID Description: OpenID DemoClick "Next"
-
Configure Capability Settings:
Enable the following options:
- ✅ Client authentication
- ✅ Authorization
- ✅ Standard flow
- ✅ Direct access grants
Click "Next"
-
Configure Access Settings:
Root URL: https://localhost:9000 Home URL: https://localhost:9000/oauth2/login Valid redirect URLs: https://localhost:9000/oauth2/login/callback Valid post logout redirect URIs: https://localhost:9000/oauth2/logout Web origins: https://localhost:9000Click "Save"
-
Retrieve OpenID Configuration:
- Access: http://localhost:8080/realms/master/.well-known/openid-configuration
- This provides all necessary endpoints
-
Get Client Secret:
- Navigate to your client in Keycloak
- Go to the "Credentials" tab
- Copy the Client Secret value
-
Update GraphXR Configuration:
Add the following to your GraphXR
config.jsfile:oauth2: { loginShowName: "Keycloak", authorizationURL: 'http://localhost:8080/realms/master/protocol/openid-connect/auth', tokenURL: 'http://localhost:8080/realms/master/protocol/openid-connect/token', userProfileURL: "http://localhost:8080/realms/master/protocol/openid-connect/userinfo", clientID: "GraphXR-OpenID", clientSecret: "{YOUR_CLIENT_SECRET}", // Replace with actual client secret scope: 'openid,email,profile', callbackURL: "https://localhost:9000/oauth2/login/callback", profileMapping: { firstName: "family_name", lastName: "given_name", email: "email", }, },
-
Replace Placeholder:
- Replace
{YOUR_CLIENT_SECRET}with the actual client secret from step 2
- Replace
Security Note: Keep your client secret secure and never commit it to public repositories.
-
Navigate to Client Creation:
-
Configure Basic Settings:
Client Type: SAML Client ID: GraphXR-SAML Name: GraphXR SAML Demo Description: A GraphXR SAML DemoClick "Next"
-
Configure Access Settings:
Root URL: https://localhost:9000 Home URL: https://localhost:9000/saml/login Valid redirect URLs: https://localhost:9000/* Valid post logout redirect URIs: https://localhost:9000/saml/logout IDP-Initiated SSO URL name: GraphXR-SAML Master SAML Processing URL: https://localhost:9000/saml/login/callback Name ID format: emailClick "Save"
-
Add SAML Attribute Mappers:
Navigate to: Client scopes > GraphXR-SAML-dedicated > Add mapper > By configuration
Add the following mappers:
Mapper Type Name User Attribute SAML Attribute Name User Property email email email User Property firstName firstName firstName User Property lastName lastName lastName For each mapper:
- Select "User Property" as mapper type
- Set SAML Attribute Name Format to "Basic"
- Click "Save"
-
Retrieve SAML Metadata:
- Access: http://localhost:8080/realms/master/protocol/saml/descriptor
- This XML contains the IdP configuration
-
Extract X.509 Certificate:
- Locate the
<ds:X509Certificate>element in the XML - Copy the certificate value (between the opening and closing tags)
- Locate the
-
Update GraphXR Configuration:
Add the following to your GraphXR
config.jsfile:saml: { loginShowName: "Keycloak-saml", path: "https://localhost:9000/saml/login", entryPoint: "http://localhost:8080/realms/master/protocol/saml/clients/GraphXR-SAML", cert: '{YOUR_CERT}', // Replace with the X509 certificate profileMapping: { email: "nameID", firstName: "firstName", lastName: "lastName" } },
-
Replace Placeholder:
- Replace
{YOUR_CERT}with the actual X.509 certificate value
- Replace
The iframe authentication allows embedding GraphXR in a third-party application with seamless authentication:
sequenceDiagram
participant TW as Third-Party Web
participant TS as Third-Party Server
participant GW as GraphXR Web
participant GS as GraphXR Server
TW->>TS: 1. Login request (OAuth2/SAML)
TS-->>TW: 2. Login response + userInfo (set token/uid in session)
TW->>GW: 3. PostMessage(token/uid) or embed URL with token/uid
GW->>GS: 4. AutoLogin request (with token/uid)
GS->>TS: 4.1 Validate token & request userInfo
TS-->>GS: 4.2 Return userInfo
GS-->>GW: 5. AutoLogin success (set session/token)
GW-->>TW: 6. Display GraphXR without login screen
Add the following to your GraphXR config.js file:
iframeAuth: {
keyName: "token",
userProfileURL: "http://localhost:8080/realms/master/protocol/openid-connect/userinfo",
profileMapping: {
email: "email",
firstName: "family_name",
lastName: "given_name",
}
},Update your GraphXR server config.js to allow iframe embedding:
cors: {
shareDefault: true, // Allow /share/default/ProjectName
allowAnonymousQuery: true, // Allow /api/neo4j/executeCommand to run Cypher
adminSub: true, // Allow /admin/sub/users to be embedded in iframe
origin: "*", // Allow all origins (or specify allowed domains)
referrerPolicy: { policy: "unsafe-url" },
frameguard: false, // Allow all GraphXR pages to be embedded in iframe
contentSecurityPolicy: false,
},Security Warning: The configuration above is permissive for development. In production:
- Restrict
originto specific domains instead of"*"- Review security implications of
allowAnonymousQuery- Consider stricter CORS policies based on your requirements
-
Install Dependencies and Start Server:
yarn && yarn start -
Access the Demo:
- URL: http://localhost:3080
- The demo app is located in
index.js
-
Embedding GraphXR with Token:
You can embed GraphXR using a URL with token parameters:
https://GraphXRServer:9000/p/default/demo-project?token={YOUR_TOKEN}&email={YOUR_EMAIL}Supported paths:
/p/default/*- Specific projects/projects- Projects list/settings- Settings page
-
Example iframe Implementation:
const iframe = document.createElement('iframe'); iframe.src = `http://localhost:9000/projects?token=${encodeURIComponent(accessToken)}&email=${encodeURIComponent(email)}`; iframe.width = "100%"; iframe.height = "800"; iframe.style = "border: 1px solid #ddd; border-radius: 4px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"; iframe.title = "GraphXR Projects"; iframe.loading = "lazy"; document.body.appendChild(iframe);
Note: See
./index.jsfor the complete implementation reference.
Before implementing iframe authentication, ensure your UserInfo API returns the correct email format:
Required Response Format:
{
"email": "user@example.com",
"family_name": "Doe",
"given_name": "John",
...
}Use the following script to test the Keycloak UserInfo API:
const token = "YOUR_ACCESS_TOKEN"; // Replace with actual token
const email = "YOUR_EMAIL"; // Replace with actual email
const userInfoApi = "http://localhost:8080/realms/master/protocol/openid-connect/userinfo";
fetch(userInfoApi, {
method: "GET",
headers: {
"Accept": "application/json, text/plain, */*",
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`,
"Email": `${email}`,
},
})
.then((res) => res.json())
.then((data) => {
console.log("UserInfo Response:", data);
// Verify required fields
if (data.email) {
console.log("✓ Email field present:", data.email);
} else {
console.error("✗ Email field missing!");
}
})
.catch((error) => {
console.error("API Error:", error);
});To obtain a test access token:
-
Using Direct Access Grants:
curl -X POST "http://localhost:8080/realms/master/protocol/openid-connect/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "client_id=GraphXR-OpenID" \ -d "client_secret=YOUR_CLIENT_SECRET" \ -d "username=demo@demo.com" \ -d "password=demo@demo.com" \ -d "grant_type=password"
-
Response will contain:
{ "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI...", "expires_in": 300, "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI...", ... } -
Use the
access_tokenvalue in your test script above.
| Issue | Solution |
|---|---|
| 401 Unauthorized | Check if token is valid and not expired |
| Missing email in response | Verify user has email set and "email" scope is included |
| CORS errors | Ensure CORS is properly configured in GraphXR |
| Token expired | Request a new token using the refresh token or re-authenticate |
- Keycloak Documentation
- OpenID Connect Specification
- SAML 2.0 Documentation
- GraphXR Configuration Guide (refer to GraphXR documentation)
- Never expose sensitive credentials in public repositories
- Use HTTPS in production environments
- Restrict CORS origins to specific domains
- Implement token expiration and refresh mechanisms
- Regularly update Keycloak and dependencies
- Use different client secrets for development and production
- Enable multi-factor authentication for admin accounts
This demo configuration is provided as-is for testing and development purposes.
Last Updated: May 21, 2026
Keycloak Version: 26.2.0

