Skip to content

Instantly share code, notes, and snippets.

@malys
Last active November 16, 2023 16:02
Show Gist options
  • Save malys/cba640896ec8081fae889f588ba125d3 to your computer and use it in GitHub Desktop.
Save malys/cba640896ec8081fae889f588ba125d3 to your computer and use it in GitHub Desktop.
[Keycloak Use cases] #keycloak #java #authentification #artillery
# https://artillery.io/docs/cli-reference/
set DEBUG=http* | artillery run -k --target host -o h:\result.json scripts && artillery report h:\result.json
// requestSpec will be the request spec for this response (currently always null)
// response is a Request.js response object
// context is the scenario context containing scenario variables
// ee is an event emitter for this scenario that we can use to add custom stats to the report
// npm install jsonwebtoken
const jwt = require('jsonwebtoken');
const util = require('util');
var richOuput=(payload)=>{
payload.iatDate= new Date(payload.iat*1000);
payload.expDate= new Date(payload.exp*1000);
console.log(util.inspect(payload, {showHidden: false, depth: null}));
}
module.exports={
basicAuthentification: ((requestParams, context, ee, next) =>{
requestParams.headers['Authorization']='Basic ' + new Buffer(context.vars.username +':' + context.vars.password).toString('base64');
return next();
}),
parseJWT:((requestParams, response, context, ee, next) =>{
console.log("------------------------------------------------")
// get the decoded payload and header
let body=JSON.parse(response.body);
if(body.access_token){
let decoded = jwt.decode(body.access_token, {complete: true});
richOuput(decoded.payload)
}
if(body.refresh_token){
let decoded = jwt.decode(body.refresh_token, {complete: true});
richOuput(decoded.payload)
}
//console.log('-> Realm role' ,decoded.payload.realm_access.roles)
//console.log('-> testPublic role',decoded.payload.resource_access.testPublic.roles)
return next();
})
};
# set DEBUG= | artillery run -k -q --target http://localhost:8080 D:\Developpement\old\keycloak-nodejs-connect\example\http\endpoints.brute-force-permanent.yml
# =============================================
# https://github.com/keycloak/keycloak-documentation/blob/master/server_admin/topics/threat/brute-force.adoc
# Permanent Lockout: true
# Max Login Failures: 5 (Maximum number of login failures permitted.)
# Quick Login Check Milli Seconds: 500 (Minimum time required between login attempts)
# Minimum Quick Login Wait: 20s (Minimum amount of time the user will be temporarily disabled if logins attempts are quicker than Quick Login Check )
# =============================================
config:
plugins:
expect: {}
phases:
- duration: 1.2
arrivalRate: 1
variables:
max: 5
realm:
- "collect"
client_id:
- "public-ws"
username:
- "bruteforce"
password:
- "bruteforce"
badPassword:
- "badpassword"
processor: "./artilleryFunctions.js"
scenarios:
- flow:
- post:
name: "1st OK"
url: "/auth/realms/{{ realm }}/protocol/openid-connect/token"
headers:
Content-Type: "application/x-www-form-urlencoded"
body: 'grant_type=password&client_id={{ client_id }}&username={{ username }}&password={{ password }}&client_secret={{ secret }}'
expect:
- statusCode: 200
- loop:
- post:
name: "Quick try"
url: "/auth/realms/{{ realm }}/protocol/openid-connect/token"
headers:
Content-Type: "application/x-www-form-urlencoded"
body: 'grant_type=password&client_id={{ client_id }}&username={{ username }}&password={{ badPassword }}&client_secret={{ secret }}'
expect:
- statusCode: 401
count: 3
#User Temporarily Locked: true
- post:
name: "User Temporarily Locked: true"
url: "/auth/realms/{{ realm }}/protocol/openid-connect/token"
headers:
Content-Type: "application/x-www-form-urlencoded"
body: 'grant_type=password&client_id={{ client_id }}&username={{ username }}&password={{ password }}&client_secret={{ secret }}'
expect:
- statusCode: 401
- think: 25
#User Temporarily Locked: false
- post:
name: "User Temporarily Locked: false"
url: "/auth/realms/{{ realm }}/protocol/openid-connect/token"
headers:
Content-Type: "application/x-www-form-urlencoded"
body: 'grant_type=password&client_id={{ client_id }}&username={{ username }}&password={{ password }}&client_secret={{ secret }}'
expect:
- statusCode: 200
- loop:
- post:
name: "Max failed"
url: "/auth/realms/{{ realm }}/protocol/openid-connect/token"
headers:
Content-Type: "application/x-www-form-urlencoded"
body: 'grant_type=password&client_id={{ client_id }}&username={{ username }}&password={{ badPassword }}&client_secret={{ secret }}'
expect:
- statusCode: 401
- think: 1
count: 1
# User Enable: false
- post:
name: "User Enable: false"
url: "/auth/realms/{{ realm }}/protocol/openid-connect/token"
headers:
Content-Type: "application/x-www-form-urlencoded"
body: 'grant_type=password&client_id={{ client_id }}&username={{ username }}&password={{ password }}&client_secret={{ secret }}'
expect:
- statusCode: 400
config:
target: "http://auth01.inte03.lbg.office.lyra:8080"
phases:
- duration: 1.9
arrivalRate: 1
variables:
realm:
- "businessRealm"
client_id:
- "businessClient"
username:
- "businessuser1"
password:
- "businessuser1"
secret:
- ""
scenarios:
- flow:
# Get list endpoints
- get:
url: "/auth/realms/{{ realm }}/.well-known/openid-configuration"
headers:
"Content-Type": "application/x-www-form-urlencoded"
#{
# "issuer":"https://xxx/auth/realms/monitoring",
# "authorization_endpoint":"https://xxx/auth/realms/monitoring/protocol/openid-connect/auth",
# "token_endpoint":"https://xxx/auth/realms/monitoring/protocol/openid-connect/token",
# "token_introspection_endpoint":"https://xxx/auth/realms/monitoring/protocol/openid-connect/token/introspect",
# "userinfo_endpoint":"https://xxx/auth/realms/monitoring/protocol/openid-connect/userinfo",
# "end_session_endpoint":"https://xxx/auth/realms/monitoring/protocol/openid-connect/logout",
# "jwks_uri":"https://xxx/auth/realms/monitoring/protocol/openid-connect/certs",
# "check_session_iframe":"https://xxx/auth/realms/monitoring/protocol/openid-connect/login-status-iframe.html",
# "grant_types_supported":[
# "authorization_code",
# "implicit",
# "refresh_token",
# "password",
# "client_credentials"
# ],
# "response_types_supported":[
# "code",
# "none",
# "id_token",
# "token",
# "id_token token",
# "code id_token",
# "code token",
# "code id_token token"
# ],
# "subject_types_supported":[
# "public",
# "pairwise"
# ],
# "id_token_signing_alg_values_supported":[
# "RS256"
# ],
# "userinfo_signing_alg_values_supported":[
# "RS256"
# ],
# "request_object_signing_alg_values_supported":[
# "none",
# "RS256"
# ],
# "response_modes_supported":[
# "query",
# "fragment",
# "form_post"
# ],
# "registration_endpoint":"https://xxx/auth/realms/monitoring/clients-registrations/openid-connect",
# "token_endpoint_auth_methods_supported":[
# "private_key_jwt",
# "client_secret_basic",
# "client_secret_post"
# ],
# "token_endpoint_auth_signing_alg_values_supported":[
# "RS256"
# ],
# "claims_supported":[
# "sub",
# "iss",
# "auth_time",
# "name",
# "given_name",
# "family_name",
# "preferred_username",
# "email"
# ],
# "claim_types_supported":[
# "normal"
# ],
# "claims_parameter_supported":false,
# "scopes_supported":[
# "openid",
# "offline_access"
# ],
# "request_parameter_supported":true,
# "request_uri_parameter_supported":true
#}
# End user authentication
- get:
url: "/auth/realms/{{ realm }}/protocol/openid-connect/auth/?client_id={{ client_id }}&redirect_uri=http://localhost&state=3518d19c-0389-473e-982e-294f3ad17f29&nonce=69cc3d0b-0db3-4275-ac81-93138b7f9bd1&response_mode=fragment&response_type=code&scope=openid"
headers:
"Content-Type": "application/x-www-form-urlencoded"
# Get public key
- get:
url: "/auth/realms/{{ realm }}/protocol/openid-connect/certs"
headers:
"Content-Type": "application/x-www-form-urlencoded"
# {
# "keys":[
# {
# "kid":"zLoBUxi-BKSRP95vssUdiTvY9crJ2Wr_YWRrfQsx5PI",
# "kty":"RSA",
# "alg":"RS256",
# "use":"sig",
# "n":"lOtl-b3DPz0fF2RZLKMssx3IyBI6fA1lh21uvGWq50bncu8iz5nmAhH-7fpDKXbAs8_eD3ZDRUhOSn_cVS6Ch6gMGxenPBe-ksOyITduR2hr9FBCVRq9X2koTp_RBNZM6owFAlwZcVqVJJNot0XI4aLzRs4LhjlaJAblfjcJv-ACs5bFaDsSbQ0ebd9zM4nXmYpe83Usj3oIj9Cn1L4ULfR4eJMw8i-gOWjnhLjy_dq45emG4VHjpK7uCZ2dhXXtvYD_pPFLcnheaAHi6H0eZZ603J1q2RPYqLs7VECgYznGAfIizfKKrMZmmePdOocTtpI56-g7sr2SNNTi8GHDQw",
# "e":"AQAB"
# }
# ]
# }
# Obtain token
- post:
url: "/auth/realms/{{ realm }}/protocol/openid-connect/token"
headers:
Content-Type: "application/x-www-form-urlencoded"
body: 'grant_type=password&client_id={{ client_id }}&username={{ username }}&password={{ password }}&client_secret={{ secret }}'
capture:
- json: "$.access_token"
as: "access_token"
- json: "$.refresh_token"
as: "refresh_token"
# {
# "access_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ6TG9CVXhpLUJLU1JQOTV2c3NVZGlUdlk5Y3JKMldyX1lXUnJmUXN4NVBJIn0.eyJqdGkiOiJhZWNiN2M3NS1mZWM2LTRkYzUtOGJmYy02M2VkZmFmYmQ4MjIiLCJleHAiOjE1MzU5Nzc3OTEsIm5iZiI6MCwiaWF0IjoxNTM1OTc3NDkxLCJpc3MiOiJodHRwczovL2FwaS1pbnRlMDMubGJnLm9mZmljZS5mci5seXJhL2F1dGgvcmVhbG1zL21vbml0b3JpbmciLCJhdWQiOiJtb25pdG9yaW5nLXB1YmxpYyIsInN1YiI6IjdlMjYzNjI5LTM0NGYtNDlhZi1hNzRiLWM5NGE2YWRkMTYzZSIsInR5cCI6IkJlYXJlciIsImF6cCI6Im1vbml0b3JpbmctcHVibGljIiwiYXV0aF90aW1lIjowLCJzZXNzaW9uX3N0YXRlIjoiOGE2ZDk5MTUtYjI2ZC00ZWNkLThhOTktYmE2MmU2ZWQ5YTI5IiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6WyIqIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sIm5hbWUiOiJtb25pdG9yaW5nIG1vbml0b3JpbmciLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJtb25pdG9yaW5nIiwiZ2l2ZW5fbmFtZSI6Im1vbml0b3JpbmciLCJmYW1pbHlfbmFtZSI6Im1vbml0b3JpbmciLCJlbWFpbCI6Im1vbml0b3JpbmdAbW9uaXRvcmluZy5sb2NhbCJ9.OPluqxymVj0hH_PAlNIpY_9zKG5kbLHKKng3mgGEgu7fRz_dboXeyX-qv99OjrFSgGIK65FHp0KU3-qURAY4qRrQJO2Nps5G9AP92LHMNlaEvC263AFZzJcPudpqXJk6upZDFbvsZcFNa0fhDb_hfrfo0dBK2rnYv7LTER3WT-i82SAgZXhikhx4wJXjIE-DtBF14at2AxqI73nJOEZ20V-EmQWMHZPx7nczwn4caEih5uBswkvyK7ZqGGEO_Ivrs5iEPQexMdoKbPik11XHpowESvH_rNSEIxf44HxiNq_E6BRXqvdvgv-h90Fthu0H42lLZNoPwlRq8v1QutqOQQ",
# "expires_in":300,
# "refresh_expires_in":1800,
# "refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ6TG9CVXhpLUJLU1JQOTV2c3NVZGlUdlk5Y3JKMldyX1lXUnJmUXN4NVBJIn0.eyJqdGkiOiIyZTRmMDg0NC1lYTkwLTQ5MjMtOTJlMC0wZmE3NGRiYWE0YmYiLCJleHAiOjE1MzU5NzkyOTEsIm5iZiI6MCwiaWF0IjoxNTM1OTc3NDkxLCJpc3MiOiJodHRwczovL2FwaS1pbnRlMDMubGJnLm9mZmljZS5mci5seXJhL2F1dGgvcmVhbG1zL21vbml0b3JpbmciLCJhdWQiOiJtb25pdG9yaW5nLXB1YmxpYyIsInN1YiI6IjdlMjYzNjI5LTM0NGYtNDlhZi1hNzRiLWM5NGE2YWRkMTYzZSIsInR5cCI6IlJlZnJlc2giLCJhenAiOiJtb25pdG9yaW5nLXB1YmxpYyIsImF1dGhfdGltZSI6MCwic2Vzc2lvbl9zdGF0ZSI6IjhhNmQ5OTE1LWIyNmQtNGVjZC04YTk5LWJhNjJlNmVkOWEyOSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX19.Zf630MInvB8Jh_dDjtyolhnEmQCg9Ae6V9vp1VUbG4UvjXWGcZ2d9_XiasfpFhKsuBYcN2LUajaPRbhZPVbGKlu0wcAWMvh0XFnjdtiELhKcdmsdsUM_KRpA3q8eTxJquBobnJ0_oe24h-M-tzB6zU47q24ApKuGRIOZlhwL-Xrj2XkJ9CoDH68CpqY3eALBBkO4YPJzgnKlWQ_yEGBKoYkmtpuZSLW5fgPINu0SETr64Lzn7EYw1FAByI8zNltBHPL5sypdjRPMa5khBzj_nQt5vhCJcPyvLY7228seZ6GUXexlvHDH0jmkEo56pcu4t8-gcrFffHCAeJACswmnYA",
# "token_type":"bearer",
# "not-before-policy":0,
# "session_state":"8a6d9915-b26d-4ecd-8a99-ba62e6ed9a29"
# }
# Get Userinfo
- get:
url: "/auth/realms/{{ realm }}/protocol/openid-connect/userinfo"
headers:
"Authorization": "Bearer {{ access_token }}"
"Content-Type": "application/x-www-form-urlencoded"
# {
# "sub":"7e263629-344f-49af-a74b-c94a6add163e",
# "name":"monitoring monitoring",
# "preferred_username":"monitoring",
# "given_name":"monitoring",
# "family_name":"monitoring",
# "email":"monitoring@monitoring.local"
# }
# Used to retrieve the active state of a token
- post:
url: "/auth/realms/{{ realm }}/protocol/openid-connect/token/introspect"
auth:
"user": "{{ client_id }}"
"pass": "{{ secret }}"
headers:
"Authorization": "Bearer {{ access_token }}"
"Content-Type": "application/x-www-form-urlencoded"
body: 'token={{ access_token }}'
# {
# "jti":"550488ab-290b-45c0-86cf-4590dddd550f",
# "exp":1535978571,
# "nbf":0,
# "iat":1535978271,
# "iss":"https://api-inte03.lbg.office.fr.lyra/auth/realms/monitoring",
# "aud":"monitoring-public",
# "sub":"7e263629-344f-49af-a74b-c94a6add163e",
# "typ":"Bearer",
# "azp":"monitoring-public",
# "auth_time":0,
# "session_state":"56eeda21-9d69-47c7-a35c-92fad9bda24e",
# "name":"monitoring monitoring",
# "given_name":"monitoring",
# "family_name":"monitoring",
# "preferred_username":"monitoring",
# "email":"monitoring@monitoring.local",
# "acr":"1",
# "allowed-origins":[
# "*"
# ],
# "realm_access":{
# "roles":[
# "uma_authorization"
# ]
# },
# "resource_access":{
# "account":{
# "roles":[
# "manage-account",
# "manage-account-links",
# "view-profile"
# ]
# }
# },
# "client_id":"monitoring-public",
# "username":"monitoring",
# "active":true
# }
# Client registration
- post:
url: "/auth/realms/{{ realm }}/clients-registrations/openid-connect/{{ client_id }}"
headers:
"Authorization": "Bearer {{ access_token }}"
"Content-Type": "application/x-www-form-urlencoded"
# IFrame status
- get:
url: "/auth/realms/{{ realm }}/protocol/openid-connect/login-status-iframe.htm"
headers:
"Authorization": "Bearer {{ access_token }}"
"Content-Type": "application/x-www-form-urlencoded"
# Logout
- post:
url: "/auth/realms/{{ realm }}/protocol/openid-connect/logout"
headers:
"Authorization": "Bearer {{ access_token }}"
"Content-Type": "application/x-www-form-urlencoded"
body: "client_id={{ client_id }}&client_secret={{ secret }}&refresh_token={{ refresh_token }}"
# In Implicit flow, clustering not support node and single logout
config:
target: "http://server1:4080"
phases:
-
arrivalRate: 1
duration: 1.92
variables:
realm:
- "myRealm"
client_id:
- "testRegister"
username:
- "t"
password:
- "t"
userID:
- "9a5e2f76-cf70-4d42-a323-10a5988e870c"
admin:
- "a"
adminPw:
- "a"
secret:
- "9436c04b-964c-42a1-9153-043eb3a90aaa"
scenarios:
- flow:
- post:
url: "/auth/realms/{{ realm }}/protocol/openid-connect/token"
headers:
Content-Type: "application/x-www-form-urlencoded"
body: 'grant_type=password&client_id={{ client_id }}&username={{ admin }}&password={{ adminPw }}&client_secret={{ secret }}'
capture:
- json: "$.access_token"
as: "access_token"
- json: "$.refresh_token"
as: "refresh_token"
- post:
url: "/auth/admin/realms/{{ realm }}/users/{{userID}}/impersonation"
headers:
Authorization: "Bearer {{ access_token }}"
Content-Type: "application/x-www-form-urlencoded"
body: 'realm={{ realm }}&user={{userID}}'
- get:
url: "http://localhost:1080/helloRest/message/toto"
headers:
Content-Type: "application/x-www-form-urlencoded"
X-Requested-With: "XMLHttpRequest"
Authorization: "Bearer {{ access_token }}"
config:
target: "http://server:3080"
phases:
- arrivalRate: 1
duration: 1.96
variables:
realm:
- "myRealm"
client_id:
- "testRegister"
username:
- "t"
password:
- "t"
secret:
- "0abd8123-1773-4597-8753-88e90ac01504"
scenarios:
- flow:
- post:
url: "/auth/realms/{{ realm }}/protocol/openid-connect/token"
headers:
Content-Type: "application/x-www-form-urlencoded"
body: 'grant_type=password&client_id={{ client_id }}&username={{ username }}&password={{ password }}&client_secret={{ secret }}'
capture:
- json: "$.access_token"
as: "access_token"
- json: "$.refresh_token"
as: "refresh_token"
- post:
url: "/auth/realms/{{ realm }}/protocol/openid-connect/token"
headers:
Content-Type: "application/x-www-form-urlencoded"
body: 'grant_type=refresh_token&client_id={{ client_id }}&refresh_token={{ refresh_token }}&client_secret={{ secret }}'
capture:
- json: "$.access_token"
as: "access_token"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment