Table of Contents
1. Introduction
Last time I explained you how to login to Elasticsearch using API Keys as authentication method. Now I want to present another method with token-service. Right now tokens do not provide same level of fine tuning security, instead they represent same rights as user used to create them.
2. Start Elasticsearch
To quickly start Elasticsearch use docker commands. Please notice that you need license to use Tokens API, free version will not work.
docker run --rm \
--name elk \
-e xpack.license.self_generated.type=trial \
-d \
-p 9200:9200 \
docker.elastic.co/elasticsearch/elasticsearch:8.10.4
After container is up and running please set password for elastic user, later on used in examples.
docker exec -it elk bash -c "(mkfifo pipe1); ( (elasticsearch-reset-password -u elastic -i < pipe1) & ( echo $'y\n123456\n123456' > pipe1) );sleep 5;rm pipe1"
3. Create Token
When you create token you specify grant type. There are 3 functional grant types at the moment:
- client_credentials
- password
- _kerberos
There is also refresh_token grant type that is used to refresh tokens created with password and _kerberos grant type as well as refresh_token itself.
3.1 Code examples to create token with client_credentials grant type.
curl -k -u elastic:123456 -XPOST "https://localhost:9200/_security/oauth2/token" -H 'content-type: application/json' -d'
{
"grant_type" : "client_credentials"
}'
In example response below you can notice access_token that from now you can use for authentication. See that default expiration is equal to 1200 seconds, means 20 minutes. You can extend that period up to 1 hour by editing static setting xpack.security.authc.token.timeout. For this particular grant type there is no refresh token available.
{
"access_token": "3eaGBBjG7QXrcjuuhyDOaAxgPs23V8MI5HT9iIkAAAA=",
"type": "Bearer",
"expires_in": 1200,
"authentication": {
"username": "elastic",
"roles": [
"superuser"
],
"full_name": null,
"email": null,
"metadata": {
"_reserved": true
},
"enabled": true,
"authentication_realm": {
"name": "reserved",
"type": "reserved"
},
"lookup_realm": {
"name": "reserved",
"type": "reserved"
},
"authentication_type": "realm"
}
}
3.2 Code example to use client_credentials token.
Example request to check health status of Elasticsearch with token authentication.
curl -k -H "Authorization: Bearer 3eaGBBjG7QXrcjuuhyDOaAxgPs23V8MI5HT9iIkAAAA=" "https://localhost:9200/_cluster/health?pretty"
3.3 Code examples to create token with password grant type.
This method require providing username and password.
curl -k -u elastic:123456 -XPOST "https://localhost:9200/_security/oauth2/token" -H 'content-type: application/json' -d'
{
"grant_type" : "password",
"username" : "elastic",
"password" : "123456"
}'
Example response below. Notice it contain refresh_token that you can use to obtain new token with refresh_token grant type.
{
"access_token": "3eaGBBgd4YCYB6NbG+Y750Q5GxqxyCEHdYdo0KgAAAA=",
"type": "Bearer",
"expires_in": 1200,
"refresh_token": "3eaGBBgVLzYRJ1XggufKo2yqRoEByCEHdYdo0KgAAAA=",
"authentication": {
"username": "elastic",
"roles": [
"superuser"
],
"full_name": null,
"email": null,
"metadata": {
"_reserved": true
},
"enabled": true,
"authentication_realm": {
"name": "reserved",
"type": "reserved"
},
"lookup_realm": {
"name": "reserved",
"type": "reserved"
},
"authentication_type": "realm"
}
}
3.4 Code example to use client_credentials token.
Below usage example. Same as previously.
curl -k -H "Authorization: Bearer 3eaGBBgd4YCYB6NbG+Y750Q5GxqxyCEHdYdo0KgAAAA=" "https://localhost:9200/_cluster/health?pretty"
3.5 Code examples to create token with refresh_token grant type.
Refreshing token like password or _kerberos can be done as below.
curl -k -H "Authorization: Bearer 3eaGBBgd4YCYB6NbG+Y750Q5GxqxyCEHdYdo0KgAAAA=" -XPOST "https://localhost:9200/_security/oauth2/token" -H 'content-type: application/json' -d'
{
"grant_type" : "refresh_token",
"refresh_token": "3eaGBBgVLzYRJ1XggufKo2yqRoEByCEHdYdo0KgAAAA="
}'
In response you will get new token
{
"access_token": "3eaGBBg/O+k0DjbCL129Sv5kpHfTdjG+ylZhz7oAAAA=",
"type": "Bearer",
"expires_in": 1200,
"refresh_token": "3eaGBBhXoPgABwZNyCp3w293bqUddjG+ylZhz7oAAAA=",
"authentication": {
"username": "elastic",
"roles": [
"superuser"
],
"full_name": null,
"email": null,
"metadata": {
"_reserved": true
},
"enabled": true,
"authentication_realm": {
"name": "reserved",
"type": "reserved"
},
"lookup_realm": {
"name": "reserved",
"type": "reserved"
},
"authentication_type": "token"
}
}
4. Delete Token
Calling delete token API will make token invalid.
4.1 Code example of deleting token
curl -k -H "Authorization: Bearer 3eaGBBg/O+k0DjbCL129Sv5kpHfTdjG+ylZhz7oAAAA=" -XDELETE "https://localhost:9200/_security/oauth2/token" -H 'content-type: application/json' -d'
{
"token": "3eaGBBg/O+k0DjbCL129Sv5kpHfTdjG+ylZhz7oAAAA="
}'
example response:
{"invalidated_tokens":1,"previously_invalidated_tokens":0,"error_count":0}
4.2 Code example of using invalidated token
If you try to use token that got invalidated you will encounter an error
curl -k -H "Authorization: Bearer 3eaGBBg/O+k0DjbCL129Sv5kpHfTdjG+ylZhz7oAAAA=" "https://localhost:9200/_cluster/health?pretty"
{
"error" : {
"root_cause" : [
{
"type" : "security_exception",
"reason" : "token expired",
"header" : {
"WWW-Authenticate" : "Bearer realm=\"security\", error=\"invalid_token\", error_description=\"The access token expired\""
}
}
],
"type" : "security_exception",
"reason" : "token expired",
"header" : {
"WWW-Authenticate" : "Bearer realm=\"security\", error=\"invalid_token\", error_description=\"The access token expired\""
}
},
"status" : 401
}
4.3 Code example of deleting refresh_token
Deleting refresh token invalidates only refresh token and matching access_token can still be used.
curl -k -u elastic:123456 -XPOST "https://localhost:9200/_security/oauth2/token" -H 'content-type: application/json' -d'
{
"grant_type" : "password",
"username" : "elastic",
"password" : "123456"
}'
# getting access token and refresh_token
# "access_token":"3eaGBBhepsmyuwnylFgBCPZtuynQg63uQ9fwd9EAAAA="
# "refresh_token":"3eaGBBjZSPsM8g4lxO4nuytwRpO4g63uQ9fwd9EAAAA="
curl -k -H "Authorization: Bearer 3eaGBBhepsmyuwnylFgBCPZtuynQg63uQ9fwd9EAAAA=" -XDELETE "https://localhost:9200/_security/oauth2/token" -H 'content-type: application/json' -d'
{
"refresh_token": "3eaGBBjZSPsM8g4lxO4nuytwRpO4g63uQ9fwd9EAAAA="
}'
{"invalidated_tokens":1,"previously_invalidated_tokens":0,"error_count":0}
Now if you use access token paired with invalidated refresh_token you will be able to authenticate.
curl -k -H "Authorization: Bearer 3eaGBBhepsmyuwnylFgBCPZtuynQg63uQ9fwd9EAAAA=" "https://localhost:9200/_cluster/health?pretty"
But if you try to use refresh_token then it will raise an error.
curl -k -H "Authorization: Bearer 3eaGBBhepsmyuwnylFgBCPZtuynQg63uQ9fwd9EAAAA=" -XPOST "https://localhost:9200/_security/oauth2/token" -H 'content-type: application/json' -d'
{
"grant_type" : "refresh_token",
"refresh_token": "3eaGBBjZSPsM8g4lxO4nuytwRpO4g63uQ9fwd9EAAAA="
}'
{"error":"invalid_grant","error_description":"token has been invalidated"}
4.4 Code example of deleting token by username and realm
You can also invalidate token that were created with specific username
curl -k -H "Authorization: Bearer 3eaGBBhDqM0cCvz+WSQqwqOYzQ8DbF6+XWEP2U0AAAA=" -XDELETE "https://localhost:9200/_security/oauth2/token" -H 'content-type: application/json' -d'
{
"username": "elastic"
}'
And realm name
curl -k -H "Authorization: Bearer 3eaGBBiyibwVd57iFYwF0tMnoxU6WW2dIMj8gVYAAAA=" -XDELETE "https://localhost:9200/_security/oauth2/token" -H 'content-type: application/json' -d'
{
"realm_name": "reserved"
}'
5. Can token create another token?
Yes, you can use token to authorize token creation.
curl -k -u elastic:123456 -XPOST "https://localhost:9200/_security/oauth2/token" -H 'content-type: application/json' -d'
{
"grant_type" : "client_credentials"
}'
# example response
# "access_token":"3eaGBBjnQxG1vngLCBApE5dD1ASpJuPczUx7qHsAAAA="
curl -k -H "Authorization: Bearer 3eaGBBjnQxG1vngLCBApE5dD1ASpJuPczUx7qHsAAAA=" -XPOST "https://localhost:9200/_security/oauth2/token" -H 'content-type: application/json' -d'
{
"grant_type" : "client_credentials"
}'
6. Summary
In this knowledge article you have learned how to deal with tokens authentication in Elasticsearch. This can be alternative for your application to connect to Elasticsearch in secure way.
One Comment