Hi Tim,
Following your suggestions and elastic documentation from OIDC, I registered two azure ad applications (1 for custom web app and 1 for elastic search realm setup) on my tenant.
Here are my realm configurations -
xpack:
security:
authc:
realms:
oidc:
oidc1:
order: 2
rp.client_id: "{client-id}"
rp.response_type: "code"
rp.requested_scopes: ["openid", "email"]
rp.redirect_uri: "https://customwebapp.azurewebsites.net"
op.issuer: "https://login.microsoftonline.com/{tenanet-id}/v2.0"
op.authorization_endpoint: "https://login.microsoftonline.com/{tenanet-id}/oauth2/v2.0/authorize"
op.token_endpoint: "https://login.microsoftonline.com/{tenanet-id}/oauth2/v2.0/token"
op.userinfo_endpoint: "https://graph.microsoft.com/oidc/userinfo"
op.endsession_endpoint: "https://login.microsoftonline.com/{tenanet-id}/oauth2/v2.0/logout"
rp.post_logout_redirect_uri: "https://customwebapp.azurewebsites.net"
op.jwkset_path: "https://login.microsoftonline.com/{tenanet-id}/discovery/v2.0/keys"
claims.principal: email
claims.groups : groups
I am able to prepare the OIDC realm and getting the redirect, state, and nonce values as a response from elastic. When I redirect the browser to the redirect URL, it asks me to authenticate with Microsoft azure ad. It does ask me to re-authenticate but doesn't ask for a password as I am already logged in to the browser session. Upon successful authentication, it returns the browser window to my web app.
Here is how I am doing the prepare api call from my angular app -
PrepElastic() {
var url = "https://{appid}.eastus2.azure.elastic.xyz.com:9243/_security/oidc/prepare"
let authorizationData = 'Basic ' + btoa('facilitator' + ':' + 'somePasswordHere');
const headers = { 'Authorization': authorizationData, 'Content-Type': 'application/json' };
const body = { "realm": "oidc1" };
return this.http.post<any>(url, body, { headers });
}
I store the state and nonce returned from the prepare call and use the same to authenticate with authenticate API but it gives me an error in the response.
AuthenticateElastic() {
var url = "https://{appid}.eastus2.azure.elastic.xyz.com:9243/_security/oidc/authenticate"
let authorizationData = 'Basic ' + btoa('facilitator' + ':' + 'somePasswordHere');
const headers = { 'Authorization': authorizationData, 'Content-Type': 'application/json' };
const body = {
"redirect_uri": this.dataShareService.getAuthCodeUrl(),
"state": this.dataShareService.getstate(),
"nonce": this.dataShareService.getnonce(),
"realm": "oidc1"
};
return this.http.post<any>(url, body, { headers });
}
Here is the error message I am getting on the browser side in response -
{"error":{"root_cause":[{"type":"security_exception","reason":"unable to authenticate user [<OIDC Token>] for action [cluster:admin/xpack/security/oidc/authenticate]","header":{"WWW-Authenticate":["Basic realm=\"security\" charset=\"UTF-8\"","Bearer realm=\"security\"","ApiKey"]}}],"type":"security_exception","reason":"unable to authenticate user [<OIDC Token>] for action [cluster:admin/xpack/security/oidc/authenticate]","header":{"WWW-Authenticate":["Basic realm=\"security\" charset=\"UTF-8\"","Bearer realm=\"security\"","ApiKey"]}},"status":401}
I turned on tracing on elastic search realm in order to find out the actual error -
PUT /_cluster/settings
{
"transient": {
"logger.org.elasticsearch.xpack.security.authc.oidc": "trace"
}
}
and I see below error message logged-
[elasticsearch.server][WARN] Authentication to realm oidc1 failed - Failed to authenticate user with OpenID Connect (Caused by ElasticsearchSecurityException[Failed to validate the response, the response did not contain a state parameter])
Reading the above message seems that we are not passing state but I can assure that we are passing all the correct values with the authenticate request.
Could you please help here?
Thanks,
Abhishek