Keycloak curl Device Authorization Grant

Keycloak curl Device Authorization Grant. Usefull in scripts for obtaining an acess token from clients that have OAuth 2.0 Device Authorization Grant enabled.

#!/bin/bash

# Keycloak Device Authorization Grant
#
# Dependencies:
#
#   'curl jq'
#
#   https://curl.se
#   https://jqlang.org


### ----------------------------

usage()
{
  printf 'Usage  : %s -a %s -r %s -c %s\n' "${0##*/}" \
    "<AUTHORITY>" "<REALM>" "<CLIENT_ID>"

  printf 'Example: %s -a "%s" -r "%s" -c "%s"\n' "${0##*/}" \
    "https://keycloak.example.com/auth" \
    "myrealm" \
    "myclient"

  exit 2
}

while getopts 'a:r:c:?h' c
do
  case $c in
    a) authority=$OPTARG ;;
    r) realm=$OPTARG ;;
    c) clientId=$OPTARG ;;
    h|?) usage ;;
  esac
done

[[ -z $authority || -z $realm || -z $clientId ]] && usage


### ----------------------------

discovery="$authority/realms/$realm/.well-known/openid-configuration"

endpoint="$(curl -sSL "$discovery" | jq -r '.device_authorization_endpoint')"

res="$(curl -sSL \
  --data-urlencode "client_id=$clientId" \
  --data-urlencode "scope=openid" \
  --url "$endpoint")"

interval="$(jq -r '.interval' <<< "$res")"
code="$(jq -r '.device_code' <<< "$res")"
verificationUri="$(jq -r '.verification_uri_complete' <<< "$res")"

read -rp "$(tput bold)Press Enter$(tput sgr0) to open $verificationUri in your browser..." >&2
open "$verificationUri"

dots="..."
while :; do
  dots=".$dots"
  printf "\rpolling%s" "$dots" >&2

  sleep "$interval"

  res="$(curl -sSL \
    --data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:device_code" \
    --data-urlencode "client_id=$clientId" \
    --data-urlencode "device_code=$code" \
    --url "$authority/realms/$realm/protocol/openid-connect/token")"

  error="$(jq -r '.error | select(.!=null)' <<< "$res")"

  if [[ -n $error ]]; then
    if [[ $error == "authorization_pending" ]]; then
      continue;
    else
      printf "ERROR:\n%s\n" "$res" >&2
      exit 1
    fi
  fi

  accessToken="$(jq -r '.access_token' <<< "$res")"

  if [[ -n $accessToken ]]; then
    printf "\n" >&2
    break;
  fi
done

printf "%s" "$accessToken"


download: device_authorization_grant.sh