How to authenticate with OIDC protocol in shell using cURL

OpenID Connect (OIDC) is an authentication protocol that is an extension of OAuth 2.0. While OAuth 2.0 is only a framework for building authorization protocols and is mainly incomplete, OIDC is a full-fledged authentication and authorization protocol. OIDC also makes heavy use of the Json Web Token (JWT) set of standards. These standards define an identity token JSON format and ways to digitally sign and encrypt that data in a compact and web-friendly way.

There are really two types of use cases when using OIDC. The first is an application that asks the Identity Management Server such as Keycloak or Okta to authenticate a user for them. After a successful login, the application will receive an identity token and an access token. The identity token contains information about the user such as username, email, and other profile information. The access token is digitally signed by the realm and contains access information (like user role mappings) that the application can use to determine what resources the user is allowed to access on the application.

cURL is a command-line tool for getting or sending data including files using URL syntax. Since cURL uses libcurl, it supports every protocol libcurl supports.

cURL supports HTTPS and performs SSL certificate verification by default when a secure protocol is specified such as HTTPS.

The script below is using Keycloak REST API to authenticate and authorize. It can authenticate both with username & password or client id & secret.

#!/usr/bin/env bash
set -e

# <configure>
UNAME=""
PASSWD=""
CLIENT_ID="hc"
CLIENT_SECRET="URTDmQvEMmcCiKjdttuMobIDcoRDp7EX"
ADDR="http://localhost"
TOKEN_URL="${ADDR}:8080/auth/realms/mytestrealm/protocol/openid-connect/token"
# </configure>

get_token() {
  curl -Lks \
    "${TOKEN_URL}" \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -d "client_id=${CLIENT_ID}" \
    -d "client_secret=${CLIENT_SECRET}" \
    -d "grant_type=client_credentials" \
    | sed -E "s/.*access_token\":\"([^\"]*)\".*/\1/g"
}

###############################################################################
#
# MAIN
#
###############################################################################

if [ "${UNAME:-dummy}" == "dummy" ] || [ "${PASSWD:-dummy}" == "dummy" ]; then
  TOKEN=$(get_token)
  AUTH="Authorization: Bearer ${TOKEN}"
else
  B64=$(echo -n "${UNAME}:${PASSWD}" | base64)
  AUTH="Authorization: Basic ${B64}"
fi

# post usage example
curl -LksX POST "<ENDPOINT_URL>" -H "${AUTH}" -o output.txt

# get usage example
curl -Lks "<ENDPOINT_URL>" -H "${AUTH}" -o output.txt