環境
keycloak-26.3.2
keycloak と openid connect 認証する flask アプリケーション。
from flask import Flask, redirect, url_for, session
from authlib.integrations.flask_client import OAuth
app = Flask(__name__)
app.secret_key = 'your-secret-key'
oauth = OAuth(app)
oauth.register(
name='keycloak',
client_id='myclient',
client_secret='6U。。gG',
server_metadata_url='http://localhost:8080/realms/myrealm/.well-known/openid-configuration',
client_kwargs={
'scope': 'openid profile email',
}
)
@app.route('/')
def index():
app.logger.info('Index page accessed')
return 'トップページ。<a href="/say">/say にアクセス</a>'
@app.route('/login')
def login():
redirect_uri = url_for('auth', _external=True)
return oauth.keycloak.authorize_redirect(redirect_uri)
@app.route('/auth')
def auth():
token = oauth.keycloak.authorize_access_token()
userinfo = oauth.keycloak.userinfo(token=token)
session['user'] = userinfo
app.logger.info(f"User info: {userinfo}")
return redirect(url_for('say'))
@app.route('/logout')
def logout():
session.pop('user', None)
return redirect('/')
@app.route('/say')
def say():
# Flaskのロガーで出力
app.logger.info(f"user in session: {'user' in session}")
if 'user' not in session:
return redirect(url_for('login'))
username = session['user'].get('preferred_username', 'unknown')
return f"hello, {username}!"
if __name__ == '__main__':
app.run(debug=True, port=8090)
その時の、パケット。
https://drive.google.com/file/d/1zmK6GrT4v5U1Yx3lP5QeKV-zXSB-kdfD/view?usp=drive_link
以前は、keycloak で、java クライアントライブラリを提供していたが、廃止された。
https://www.keycloak.org/2023/03/adapter-deprecation-update
上記で参照されていたもの。最近は、こういうのがあるから、うちはやめて、こっちを使ってよ。とのこと。
なあんだ。これはただの、仕様で、 WildFly, Quarkus など一部のフレームワークでしか、サポートされていない。
https://github.com/keycloak/keycloak-quickstarts/tree/main/jakarta
ここでも、サンプルは、 WildFly が前提。まあ、RedHat 製だから当然。oidc.json にサーバーの設定を書く。
pac4j はなんでもできる定番らしいが、よくわからん。デモを読んでもわからん。jakarta サポートの現状がわからん。
https://www.pac4j.org/
https://github.com/pac4j/jee-pac4j-demo/tree/master
有償らしい
古そうだけど、OpenIDファウンデーション・ジャパンで、言及されていた google 製の oauth クライアントライブラリ。
https://eiwg.openid.or.jp/phase3/samples/implementation/Java
https://github.com/googleapis/google-oauth-java-client
最後に、本家の java api を生で使えばなんでもできるだろうが。
https://www.keycloak.org/docs-api/latest/javadocs/index.html
PS C:\Users\kanda\keycloak-26.3.2> bin\kcadm.bat config credentials --server http://localhost:8080 --realm master --user admin
Logging into http://localhost:8080 as user admin of realm master
Enter password:
PS C:\Users\kanda\keycloak-26.3.2> .\bin\kcadm.bat get realms
[ {
"id" : "0ca1bab3-cfde-4708-998e-680f245ec9cf",
"realm" : "myrealm",
"notBefore" : 0,
"defaultSignatureAlgorithm" : "RS256",
"revokeRefreshToken" : false,
"refreshTokenMaxReuse" : 0,
"accessTokenLifespan" : 300,
"accessTokenLifespanForImplicitFlow" : 900,
"ssoSessionIdleTimeout" : 1800,
"ssoSessionMaxLifespan" : 36000,
"ssoSessionIdleTimeoutRememberMe" : 0,
"ssoSessionMaxLifespanRememberMe" : 0,
"offlineSessionIdleTimeout" : 2592000,
"offlineSessionMaxLifespanEnabled" : false,
"offlineSessionMaxLifespan" : 5184000,
"clientSessionIdleTimeout" : 0,
"clientSessionMaxLifespan" : 0,
"clientOfflineSessionIdleTimeout" : 0,
"clientOfflineSessionMaxLifespan" : 0,
"accessCodeLifespan" : 60,
"accessCodeLifespanUserAction" : 300,
"accessCodeLifespanLogin" : 1800,
"actionTokenGeneratedByAdminLifespan" : 43200,
"actionTokenGeneratedByUserLifespan" : 300,
"oauth2DeviceCodeLifespan" : 600,
"oauth2DevicePollingInterval" : 5,
"enabled" : true,
"sslRequired" : "external",
"registrationAllowed" : false,
"registrationEmailAsUsername" : false,
"rememberMe" : false,
"verifyEmail" : false,
"loginWithEmailAllowed" : true,
"duplicateEmailsAllowed" : false,
"resetPasswordAllowed" : false,
"editUsernameAllowed" : false,
"bruteForceProtected" : false,
"permanentLockout" : false,
"maxTemporaryLockouts" : 0,
"bruteForceStrategy" : "MULTIPLE",
"maxFailureWaitSeconds" : 900,
"minimumQuickLoginWaitSeconds" : 60,
"waitIncrementSeconds" : 60,
"quickLoginCheckMilliSeconds" : 1000,
"maxDeltaTimeSeconds" : 43200,
"failureFactor" : 30,
"defaultRole" : {
"id" : "56725035-4eb1-4c96-bd2d-3efb33168e99",
"name" : "default-roles-myrealm",
"description" : "${role_default-roles}",
"composite" : true,
"clientRole" : false,
"containerId" : "0ca1bab3-cfde-4708-998e-680f245ec9cf"
},
"requiredCredentials" : [ "password" ],
"otpPolicyType" : "totp",
"otpPolicyAlgorithm" : "HmacSHA1",
"otpPolicyInitialCounter" : 0,
"otpPolicyDigits" : 6,
"otpPolicyLookAheadWindow" : 1,
"otpPolicyPeriod" : 30,
"otpPolicyCodeReusable" : false,
"otpSupportedApplications" : [ "totpAppFreeOTPName", "totpAppGoogleName", "totpAppMicrosoftAuthenticatorName" ],
"webAuthnPolicyRpEntityName" : "keycloak",
"webAuthnPolicySignatureAlgorithms" : [ "ES256", "RS256" ],
"webAuthnPolicyRpId" : "",
"webAuthnPolicyAttestationConveyancePreference" : "not specified",
"webAuthnPolicyAuthenticatorAttachment" : "not specified",
"webAuthnPolicyRequireResidentKey" : "not specified",
"webAuthnPolicyUserVerificationRequirement" : "not specified",
"webAuthnPolicyCreateTimeout" : 0,
"webAuthnPolicyAvoidSameAuthenticatorRegister" : false,
"webAuthnPolicyAcceptableAaguids" : [ ],
"webAuthnPolicyExtraOrigins" : [ ],
"webAuthnPolicyPasswordlessRpEntityName" : "keycloak",
"webAuthnPolicyPasswordlessSignatureAlgorithms" : [ "ES256", "RS256" ],
"webAuthnPolicyPasswordlessRpId" : "",
"webAuthnPolicyPasswordlessAttestationConveyancePreference" : "not specified",
"webAuthnPolicyPasswordlessAuthenticatorAttachment" : "not specified",
"webAuthnPolicyPasswordlessRequireResidentKey" : "not specified",
"webAuthnPolicyPasswordlessUserVerificationRequirement" : "not specified",
"webAuthnPolicyPasswordlessCreateTimeout" : 0,
"webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister" : false,
"webAuthnPolicyPasswordlessAcceptableAaguids" : [ ],
"webAuthnPolicyPasswordlessExtraOrigins" : [ ],
"browserSecurityHeaders" : {
"contentSecurityPolicyReportOnly" : "",
"xContentTypeOptions" : "nosniff",
"referrerPolicy" : "no-referrer",
"xRobotsTag" : "none",
"xFrameOptions" : "SAMEORIGIN",
"contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';",
"strictTransportSecurity" : "max-age=31536000; includeSubDomains"
},
"smtpServer" : { },
"eventsEnabled" : false,
"eventsListeners" : [ "jboss-logging" ],
"enabledEventTypes" : [ ],
"adminEventsEnabled" : false,
"adminEventsDetailsEnabled" : false,
"internationalizationEnabled" : false,
"browserFlow" : "browser",
"registrationFlow" : "registration",
"directGrantFlow" : "direct grant",
"resetCredentialsFlow" : "reset credentials",
"clientAuthenticationFlow" : "clients",
"dockerAuthenticationFlow" : "docker auth",
"firstBrokerLoginFlow" : "first broker login",
"attributes" : {
"cibaBackchannelTokenDeliveryMode" : "poll",
"cibaExpiresIn" : "120",
"cibaAuthRequestedUserHint" : "login_hint",
"oauth2DeviceCodeLifespan" : "600",
"oauth2DevicePollingInterval" : "5",
"parRequestUriLifespan" : "60",
"cibaInterval" : "5",
"realmReusableOtpCode" : "false"
},
"userManagedAccessAllowed" : false,
"organizationsEnabled" : false,
"verifiableCredentialsEnabled" : false,
"adminPermissionsEnabled" : false,
"clientProfiles" : {
"profiles" : [ ]
},
"clientPolicies" : {
"policies" : [ ]
}
}, {
"id" : "e42d2adf-b57a-4968-849b-981c11dc2423",
"realm" : "master",
"displayName" : "Keycloak",
"displayNameHtml" : "<div class=\"kc-logo-text\"><span>Keycloak</span></div>",
"notBefore" : 0,
"defaultSignatureAlgorithm" : "RS256",
"revokeRefreshToken" : false,
"refreshTokenMaxReuse" : 0,
"accessTokenLifespan" : 60,
"accessTokenLifespanForImplicitFlow" : 900,
"ssoSessionIdleTimeout" : 1800,
"ssoSessionMaxLifespan" : 36000,
"ssoSessionIdleTimeoutRememberMe" : 0,
"ssoSessionMaxLifespanRememberMe" : 0,
"offlineSessionIdleTimeout" : 2592000,
"offlineSessionMaxLifespanEnabled" : false,
"offlineSessionMaxLifespan" : 5184000,
"clientSessionIdleTimeout" : 0,
"clientSessionMaxLifespan" : 0,
"clientOfflineSessionIdleTimeout" : 0,
"clientOfflineSessionMaxLifespan" : 0,
"accessCodeLifespan" : 60,
"accessCodeLifespanUserAction" : 300,
"accessCodeLifespanLogin" : 1800,
"actionTokenGeneratedByAdminLifespan" : 43200,
"actionTokenGeneratedByUserLifespan" : 300,
"oauth2DeviceCodeLifespan" : 600,
"oauth2DevicePollingInterval" : 5,
"enabled" : true,
"sslRequired" : "external",
"registrationAllowed" : false,
"registrationEmailAsUsername" : false,
"rememberMe" : false,
"verifyEmail" : false,
"loginWithEmailAllowed" : true,
"duplicateEmailsAllowed" : false,
"resetPasswordAllowed" : false,
"editUsernameAllowed" : false,
"bruteForceProtected" : false,
"permanentLockout" : false,
"maxTemporaryLockouts" : 0,
"bruteForceStrategy" : "MULTIPLE",
"maxFailureWaitSeconds" : 900,
"minimumQuickLoginWaitSeconds" : 60,
"waitIncrementSeconds" : 60,
"quickLoginCheckMilliSeconds" : 1000,
"maxDeltaTimeSeconds" : 43200,
"failureFactor" : 30,
"defaultRole" : {
"id" : "50d2b96d-c716-4533-bbe0-e240c560a07d",
"name" : "default-roles-master",
"description" : "${role_default-roles}",
"composite" : true,
"clientRole" : false,
"containerId" : "e42d2adf-b57a-4968-849b-981c11dc2423"
},
"requiredCredentials" : [ "password" ],
"otpPolicyType" : "totp",
"otpPolicyAlgorithm" : "HmacSHA1",
"otpPolicyInitialCounter" : 0,
"otpPolicyDigits" : 6,
"otpPolicyLookAheadWindow" : 1,
"otpPolicyPeriod" : 30,
"otpPolicyCodeReusable" : false,
"otpSupportedApplications" : [ "totpAppFreeOTPName", "totpAppGoogleName", "totpAppMicrosoftAuthenticatorName" ],
"webAuthnPolicyRpEntityName" : "keycloak",
"webAuthnPolicySignatureAlgorithms" : [ "ES256", "RS256" ],
"webAuthnPolicyRpId" : "",
"webAuthnPolicyAttestationConveyancePreference" : "not specified",
"webAuthnPolicyAuthenticatorAttachment" : "not specified",
"webAuthnPolicyRequireResidentKey" : "not specified",
"webAuthnPolicyUserVerificationRequirement" : "not specified",
"webAuthnPolicyCreateTimeout" : 0,
"webAuthnPolicyAvoidSameAuthenticatorRegister" : false,
"webAuthnPolicyAcceptableAaguids" : [ ],
"webAuthnPolicyExtraOrigins" : [ ],
"webAuthnPolicyPasswordlessRpEntityName" : "keycloak",
"webAuthnPolicyPasswordlessSignatureAlgorithms" : [ "ES256", "RS256" ],
"webAuthnPolicyPasswordlessRpId" : "",
"webAuthnPolicyPasswordlessAttestationConveyancePreference" : "not specified",
"webAuthnPolicyPasswordlessAuthenticatorAttachment" : "not specified",
"webAuthnPolicyPasswordlessRequireResidentKey" : "not specified",
"webAuthnPolicyPasswordlessUserVerificationRequirement" : "not specified",
"webAuthnPolicyPasswordlessCreateTimeout" : 0,
"webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister" : false,
"webAuthnPolicyPasswordlessAcceptableAaguids" : [ ],
"webAuthnPolicyPasswordlessExtraOrigins" : [ ],
"browserSecurityHeaders" : {
"contentSecurityPolicyReportOnly" : "",
"xContentTypeOptions" : "nosniff",
"referrerPolicy" : "no-referrer",
"xRobotsTag" : "none",
"xFrameOptions" : "SAMEORIGIN",
"contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';",
"strictTransportSecurity" : "max-age=31536000; includeSubDomains"
},
"smtpServer" : { },
"eventsEnabled" : false,
"eventsListeners" : [ "jboss-logging" ],
"enabledEventTypes" : [ ],
"adminEventsEnabled" : false,
"adminEventsDetailsEnabled" : false,
"internationalizationEnabled" : false,
"browserFlow" : "browser",
"registrationFlow" : "registration",
"directGrantFlow" : "direct grant",
"resetCredentialsFlow" : "reset credentials",
"clientAuthenticationFlow" : "clients",
"dockerAuthenticationFlow" : "docker auth",
"firstBrokerLoginFlow" : "first broker login",
"attributes" : {
"cibaBackchannelTokenDeliveryMode" : "poll",
"cibaExpiresIn" : "120",
"cibaAuthRequestedUserHint" : "login_hint",
"parRequestUriLifespan" : "60",
"cibaInterval" : "5",
"realmReusableOtpCode" : "false"
},
"userManagedAccessAllowed" : false,
"organizationsEnabled" : false,
"verifiableCredentialsEnabled" : false,
"adminPermissionsEnabled" : false,
"clientProfiles" : {
"profiles" : [ ]
},
"clientPolicies" : {
"policies" : [ ]
}
} ]
PS C:\Users\kanda\keycloak-26.3.2> .\bin\kcadm.bat get clients -r myrealm
[ {
"id" : "e778297c-2c4c-4562-bd04-b8fc22a48250",
"clientId" : "account",
"name" : "${client_account}",
"rootUrl" : "${authBaseUrl}",
"baseUrl" : "/realms/myrealm/account/",
"surrogateAuthRequired" : false,
"enabled" : true,
"alwaysDisplayInConsole" : false,
"clientAuthenticatorType" : "client-secret",
"redirectUris" : [ "/realms/myrealm/account/*" ],
"webOrigins" : [ ],
"notBefore" : 0,
"bearerOnly" : false,
"consentRequired" : false,
"standardFlowEnabled" : true,
"implicitFlowEnabled" : false,
"directAccessGrantsEnabled" : false,
"serviceAccountsEnabled" : false,
"publicClient" : true,
"frontchannelLogout" : false,
"protocol" : "openid-connect",
"attributes" : {
"realm_client" : "false",
"post.logout.redirect.uris" : "+"
},
"authenticationFlowBindingOverrides" : { },
"fullScopeAllowed" : false,
"nodeReRegistrationTimeout" : 0,
"defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ],
"optionalClientScopes" : [ "address", "phone", "offline_access", "organization", "microprofile-jwt" ],
"access" : {
"view" : true,
"configure" : true,
"manage" : true
}
}, {
"id" : "c04d8fad-1b36-41c4-85d5-c841441732bf",
"clientId" : "account-console",
"name" : "${client_account-console}",
"rootUrl" : "${authBaseUrl}",
"baseUrl" : "/realms/myrealm/account/",
"surrogateAuthRequired" : false,
"enabled" : true,
"alwaysDisplayInConsole" : false,
"clientAuthenticatorType" : "client-secret",
"redirectUris" : [ "/realms/myrealm/account/*" ],
"webOrigins" : [ ],
"notBefore" : 0,
"bearerOnly" : false,
"consentRequired" : false,
"standardFlowEnabled" : true,
"implicitFlowEnabled" : false,
"directAccessGrantsEnabled" : false,
"serviceAccountsEnabled" : false,
"publicClient" : true,
"frontchannelLogout" : false,
"protocol" : "openid-connect",
"attributes" : {
"realm_client" : "false",
"post.logout.redirect.uris" : "+",
"pkce.code.challenge.method" : "S256"
},
"authenticationFlowBindingOverrides" : { },
"fullScopeAllowed" : false,
"nodeReRegistrationTimeout" : 0,
"protocolMappers" : [ {
"id" : "48f3bad9-7eae-49f9-9407-6fe0d45acc16",
"name" : "audience resolve",
"protocol" : "openid-connect",
"protocolMapper" : "oidc-audience-resolve-mapper",
"consentRequired" : false,
"config" : { }
} ],
"defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ],
"optionalClientScopes" : [ "address", "phone", "offline_access", "organization", "microprofile-jwt" ],
"access" : {
"view" : true,
"configure" : true,
"manage" : true
}
}, {
"id" : "05ce7886-2595-4406-9780-6d13d9294684",
"clientId" : "admin-cli",
"name" : "${client_admin-cli}",
"surrogateAuthRequired" : false,
"enabled" : true,
"alwaysDisplayInConsole" : false,
"clientAuthenticatorType" : "client-secret",
"redirectUris" : [ ],
"webOrigins" : [ ],
"notBefore" : 0,
"bearerOnly" : false,
"consentRequired" : false,
"standardFlowEnabled" : false,
"implicitFlowEnabled" : false,
"directAccessGrantsEnabled" : true,
"serviceAccountsEnabled" : false,
"publicClient" : true,
"frontchannelLogout" : false,
"protocol" : "openid-connect",
"attributes" : {
"realm_client" : "false",
"client.use.lightweight.access.token.enabled" : "true"
},
"authenticationFlowBindingOverrides" : { },
"fullScopeAllowed" : true,
"nodeReRegistrationTimeout" : 0,
"defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ],
"optionalClientScopes" : [ "address", "phone", "offline_access", "organization", "microprofile-jwt" ],
"access" : {
"view" : true,
"configure" : true,
"manage" : true
}
}, {
"id" : "142a0415-d8b0-41bb-b156-30d8bf8c3f1d",
"clientId" : "broker",
"name" : "${client_broker}",
"surrogateAuthRequired" : false,
"enabled" : true,
"alwaysDisplayInConsole" : false,
"clientAuthenticatorType" : "client-secret",
"redirectUris" : [ ],
"webOrigins" : [ ],
"notBefore" : 0,
"bearerOnly" : true,
"consentRequired" : false,
"standardFlowEnabled" : true,
"implicitFlowEnabled" : false,
"directAccessGrantsEnabled" : false,
"serviceAccountsEnabled" : false,
"publicClient" : false,
"frontchannelLogout" : false,
"protocol" : "openid-connect",
"attributes" : {
"realm_client" : "true"
},
"authenticationFlowBindingOverrides" : { },
"fullScopeAllowed" : false,
"nodeReRegistrationTimeout" : 0,
"defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ],
"optionalClientScopes" : [ "address", "phone", "offline_access", "organization", "microprofile-jwt" ],
"access" : {
"view" : true,
"configure" : true,
"manage" : true
}
}, {
"id" : "ee87d14c-0298-4db3-b946-58a0fa8dd48c",
"clientId" : "myclient",
"name" : "",
"description" : "",
"rootUrl" : "",
"adminUrl" : "",
"baseUrl" : "",
"surrogateAuthRequired" : false,
"enabled" : true,
"alwaysDisplayInConsole" : false,
"clientAuthenticatorType" : "client-secret",
"secret" : "6U2LGiUUUHDU4xuH8lEFmM9doqNVzBgG",
"redirectUris" : [ "http://localhost:8090/*" ],
"webOrigins" : [ "http://localhost:8090" ],
"notBefore" : 0,
"bearerOnly" : false,
"consentRequired" : false,
"standardFlowEnabled" : true,
"implicitFlowEnabled" : false,
"directAccessGrantsEnabled" : false,
"serviceAccountsEnabled" : false,
"publicClient" : false,
"frontchannelLogout" : true,
"protocol" : "openid-connect",
"attributes" : {
"realm_client" : "false",
"oidc.ciba.grant.enabled" : "false",
"client.secret.creation.time" : "1754695007",
"backchannel.logout.session.required" : "true",
"standard.token.exchange.enabled" : "false",
"frontchannel.logout.session.required" : "true",
"oauth2.device.authorization.grant.enabled" : "false",
"display.on.consent.screen" : "false",
"backchannel.logout.revoke.offline.tokens" : "false"
},
"authenticationFlowBindingOverrides" : { },
"fullScopeAllowed" : true,
"nodeReRegistrationTimeout" : -1,
"defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ],
"optionalClientScopes" : [ "address", "phone", "offline_access", "organization", "microprofile-jwt" ],
"access" : {
"view" : true,
"configure" : true,
"manage" : true
}
}, {
"id" : "94cad8b9-876e-4eaa-b570-71ea41df7355",
"clientId" : "realm-management",
"name" : "${client_realm-management}",
"surrogateAuthRequired" : false,
"enabled" : true,
"alwaysDisplayInConsole" : false,
"clientAuthenticatorType" : "client-secret",
"redirectUris" : [ ],
"webOrigins" : [ ],
"notBefore" : 0,
"bearerOnly" : true,
"consentRequired" : false,
"standardFlowEnabled" : true,
"implicitFlowEnabled" : false,
"directAccessGrantsEnabled" : false,
"serviceAccountsEnabled" : false,
"publicClient" : false,
"frontchannelLogout" : false,
"protocol" : "openid-connect",
"attributes" : {
"realm_client" : "true"
},
"authenticationFlowBindingOverrides" : { },
"fullScopeAllowed" : false,
"nodeReRegistrationTimeout" : 0,
"defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ],
"optionalClientScopes" : [ "address", "phone", "offline_access", "organization", "microprofile-jwt" ],
"access" : {
"view" : true,
"configure" : true,
"manage" : true
}
}, {
"id" : "0b2479f1-233e-4867-bab2-e1b997155575",
"clientId" : "security-admin-console",
"name" : "${client_security-admin-console}",
"rootUrl" : "${authAdminUrl}",
"baseUrl" : "/admin/myrealm/console/",
"surrogateAuthRequired" : false,
"enabled" : true,
"alwaysDisplayInConsole" : false,
"clientAuthenticatorType" : "client-secret",
"redirectUris" : [ "/admin/myrealm/console/*" ],
"webOrigins" : [ "+" ],
"notBefore" : 0,
"bearerOnly" : false,
"consentRequired" : false,
"standardFlowEnabled" : true,
"implicitFlowEnabled" : false,
"directAccessGrantsEnabled" : false,
"serviceAccountsEnabled" : false,
"publicClient" : true,
"frontchannelLogout" : false,
"protocol" : "openid-connect",
"attributes" : {
"realm_client" : "false",
"client.use.lightweight.access.token.enabled" : "true",
"post.logout.redirect.uris" : "+",
"pkce.code.challenge.method" : "S256"
},
"authenticationFlowBindingOverrides" : { },
"fullScopeAllowed" : true,
"nodeReRegistrationTimeout" : 0,
"protocolMappers" : [ {
"id" : "8d0c5673-fb9b-4a77-abca-6902d53951dd",
"name" : "locale",
"protocol" : "openid-connect",
"protocolMapper" : "oidc-usermodel-attribute-mapper",
"consentRequired" : false,
"config" : {
"introspection.token.claim" : "true",
"userinfo.token.claim" : "true",
"user.attribute" : "locale",
"id.token.claim" : "true",
"access.token.claim" : "true",
"claim.name" : "locale",
"jsonType.label" : "String"
}
} ],
"defaultClientScopes" : [ "web-origins", "acr", "roles", "profile", "basic", "email" ],
"optionalClientScopes" : [ "address", "phone", "offline_access", "organization", "microprofile-jwt" ],
"access" : {
"view" : true,
"configure" : true,
"manage" : true
}
} ]
No. Time Source Destination Protocol Length Info
4 0.001886 127.0.0.1 127.0.0.1 HTTP 1019 GET /admin/realms HTTP/1.1
Frame 4: 1019 bytes on wire (8152 bits), 1019 bytes captured (8152 bits) on interface \Device\NPF_Loopback, id 0
Null/Loopback
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
Transmission Control Protocol, Src Port: 53001, Dst Port: 8080, Seq: 1, Ack: 1, Len: 975
Hypertext Transfer Protocol
GET /admin/realms HTTP/1.1\r\n
[…] Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIzR0phUXp6VGNfTW9jY0xSTnE1UFdYYmdTTmdzRUlLeDNETTQxVWwxVGZFIn0.eyJleHAiOjE3NTU0MDIzNzIsImlhdCI6MTc1NTM5ODc3MiwianRpIjoib25sdHJvOjFmYzg4ZjkxLThiMDMtZTFjOC0xMDRkLTV
Accept: application/json\r\n
Host: localhost:8080\r\n
Connection: Keep-Alive\r\n
User-Agent: Apache-HttpClient/4.5.14 (Java/21.0.7)\r\n
Accept-Encoding: gzip,deflate\r\n
\r\n
[Response in frame: 6]
[Full request URI: http://localhost:8080/admin/realms]
No. Time Source Destination Protocol Length Info
6 0.011722 127.0.0.1 127.0.0.1 HTTP/JSON 9450 HTTP/1.1 200 OK , JSON (application/json)
Frame 6: 9450 bytes on wire (75600 bits), 9450 bytes captured (75600 bits) on interface \Device\NPF_Loopback, id 0
Null/Loopback
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
Transmission Control Protocol, Src Port: 8080, Dst Port: 53001, Seq: 1, Ack: 976, Len: 9406
Hypertext Transfer Protocol, has 3 chunks (including last chunk)
HTTP/1.1 200 OK\r\n
transfer-encoding: chunked\r\n
Cache-Control: no-cache\r\n
Content-Type: application/json;charset=UTF-8\r\n
Referrer-Policy: no-referrer\r\n
Strict-Transport-Security: max-age=31536000; includeSubDomains\r\n
X-Content-Type-Options: nosniff\r\n
X-Frame-Options: SAMEORIGIN\r\n
\r\n
[Request in frame: 4]
[Time since request: 0.009836000 seconds]
[Request URI: /admin/realms]
[Full request URI: http://localhost:8080/admin/realms]
HTTP chunked response
File Data: 9112 bytes
JavaScript Object Notation: application/json
PS C:\Users\kanda\keycloak-26.3.2> .\bin\kcadm.bat get --help
Usage: kcadm.bat get ENDPOINT_URI [ARGUMENTS]
Command to retrieve existing resources from the server.
Use 'kcadm.bat config credentials' to establish an authenticated session, or use CREDENTIALS OPTIONS
to perform one time authentication.
Arguments:
Global options:
-x Print full stack trace when exiting with error
--config Path to the config file (C:\Users\kanda/.keycloak/kcadm.config by default)
--no-config Don't use config file - no authentication info is loaded or saved
--token Token to use to invoke on Keycloak. Other credential may be ignored if this flag is set.
--truststore PATH Path to a truststore containing trusted certificates
--trustpass PASSWORD Truststore password (prompted for if not specified, --truststore is used, and the KC_CLI_TRUSTSTORE_PASSWORD env property is not defined)
CREDENTIALS OPTIONS Same set of options as accepted by 'kcadm.bat config credentials' in order to establish
an authenticated sessions. In combination with --no-config option this allows transient
(on-the-fly) authentication to be performed which leaves no tokens in config file.
ENDPOINT_URI URI used to compose a target resource url. Commonly used values are:
realms, users, roles, groups, clients, keys, serverinfo, components ...
If it starts with 'http://' then it will be used as target resource url
-r, --target-realm REALM Target realm to issue requests against if not the one authenticated against
-q, --query NAME=VALUE Add to request URI a NAME query parameter with value VALUE, for example --query q=username:admin
-h, --header NAME=VALUE Set request header NAME to VALUE
-o, --offset OFFSET Set paging offset - adds a query parameter 'first' which some endpoints recognize
-l, --limit LIMIT Set limit to number of items in result - adds a query parameter 'max'
which some endpoints recognize
-H, --print-headers Print response headers
-F, --fields FILTER A filter pattern to specify which fields of a JSON response to output
-c, --compressed Don't pretty print the output
--format FORMAT Set output format to comma-separated-values by using 'csv'. Default format is 'json'
--noquotes Don't quote strings when output format is 'csv'
-a, --admin-root URL URL of Admin REST endpoint root if not default - e.g. http://localhost:8080/admin
Output results can be filtered by using '--fields' and a filter pattern. Filtering is performed by processing each item in a result set
and applying filter on it. A pattern is defined as a comma separated list of attribute specifiers. Use '*' in a specifier to include all
attributes. Use attribute name, to include individual attributes. Use '-' prefix to exclude individual attributes.
Use brackets after attribute specifier to specify a pattern for child attributes. For example:
'protocolMappers(id,config)' only return attributes 'id' and 'config' of protocolMapper top level attribute
'*(*(*))' return all attributes three levels deep
'*(*),-id,-protocolMappers' return all attributes two levels deep, excluding 'id', and 'protocolMappers' top level attributes
If attribute of object type is included, but its children are not specified by using brackets, then an empty object will be returned - '{}'.
Usually you will want to specify object attributes with brackets to display them fully - e.g. 'protocolMappers(*(*))'
Examples:
Get all realms, displaying only some of the attributes:
c:\> kcadm.bat get realms --fields id,realm,enabled
Get 'demorealm':
c:\> kcadm.bat get realms/demorealm
Get all configured identity providers in demorealm, displaying only some of the attributes:
c:\> kcadm.bat get identity-provider/instances -r demorealm --fields alias,providerId,enabled
Get all clients in demorealm, displaying only some of the attributes:
c:\> kcadm.bat get clients -r demorealm --fields 'id,clientId,protocolMappers(id,name,protocol,protocolMapper)'
Get specific client in demorealm, and remove 'id', and 'protocolMappers' attributes in order to use
it as a template (replace ID with client's 'id'):
c:\> kcadm.bat get clients/ID -r demorealm --fields '*(*),-id,-protocolMappers' > realm-template.json
Display first level attributes available on 'serverinfo' resource:
c:\> kcadm.bat get serverinfo -r demorealm --fields '*'
Display system info and memory info:
c:\> kcadm.bat get serverinfo -r demorealm --fields 'systemInfo(*),memoryInfo(*)'
Get adapter configuration for the client (replace ID with client's 'id'):
c:\> kcadm.bat get clients/ID/installation/providers/keycloak-oidc-keycloak-json -r demorealm
Get first 100 users at the most:
c:\> kcadm.bat get users -r demorealm --offset 0 --limit 100
Note: 'users' endpoint knows how to handle --offset and --limit. Most other endpoints don't.
Get all users whose 'username' matches '*test*' pattern, and 'email' matches '*@google.com*':
c:\> kcadm.bat get users -r demorealm -q q="username:test email:@google.com"
Note: it is the 'users' endpoint that interprets query parameters 'username', and 'email' in such a way that
it results in the described semantics. Another endpoint may provide a different semantics.
Use 'kcadm.bat help' for general information and a list of commands
PS C:\Users\kanda\keycloak-26.3.2>