Skip to main content
Version: 12.x (Current)

Client Credentials

The Client Credentials service allows to expose APIs to perform OAuth2 compliant client credential flows with third-party providers. This means that authorized service accounts can obtain an access token to access protected resources, without the need to involve the user.

In this section, you will learn how to configure the client-credentials service step by step.

Create the client collection

This service uses a crud-service collection to handle clients.

Create a CRUD collection in the MongoDB CRUD section of the Console with the name clients (you can choose also another name if already taken in your project), download these fields, and import them into the Console (find out how to import fields here).

info

We suggest that you create a unique index for the clientId field (which must not be duplicated).

Environment variables

This service is configurable with the following environment variables:

  • USERID_HEADER_KEY (default to miauserid): name of the header carrying the identifier of the calling user;
  • ADDITIONAL_HEADERS_TO_PROXY (default to miauserid,miausergroups,miauserproperties): list of comma separated header keys which will be proxied to any external http service the Client Credentials might call (for the moment, is just the CRUD Service). By default, the Client Credentials services proxies the following headers: Request-Id, X-Request-Id, X-Forwarded-For, X-Forwarded-Proto, X-Forwarded-Host;
  • LOG_LEVEL (default to info): level of the log. It could be trace, debug, info, warn, error, fatal;
  • HTTP_PORT (default to 3000): port where the web server is exposed;
  • SERVICE_PREFIX: path prefix for all the specified endpoints (different from the status routes);
  • DELAY_SHUTDOWN_SECONDS (default to 10 seconds): seconds to wait before starting the graceful shutdown. This delay is required in k8s to await for the dns rotation;
  • CRUD_CLIENT_BASE_URL (required): base url to the crud collection containing the client information. Example: http://crud-service/clients where clients is the internal endpoint exposed for the clients collection created in the previous step;
  • CLIENT_ID_HASH_SALT (required): static hash salt used to save the client id. For example, can be a random string of 256 characters;
  • CLIENT_SECRET_HASH_COST (default to 10): the cost to generate the hash of the client secret (using bcrypt);
  • CREDENTIALS_MONGODB_URL (required): the mongo url pointing to the db which will handle the credentials information;
  • CREDENTIALS_COLLECTION_NAME (default to credentials): collection to save the credentials information;
  • MONGODB_CREDENTIALS_DATABASE_NAME: the mongo db name which will include the credentials collection. If not set, it is taken from the MongoDB URL configured in CREDENTIALS_MONGODB_URL env var;
  • PRIVATE_RSA_KEY_FILE_PATH (required): path to mount the private RSA key. Click here to see how to create it;
  • PRIVATE_KEY_PASSWORD: password to decrypt the RSA key, if it is encrypted with a password. If it is empty, RSA key is treated as a non protected RSA key;
  • PRIVATE_RSA_KEY_ID (required): id of the private key. It will be added to the kid of the generated JWT. This is a random string;
  • MIA_JWT_ISSUER (required): string containing the issuer to fill the JWT claims. During the login flow, it is added as iss;
  • MIA_JWT_EXPIRES_IN (required): expiration time for the generated JWT, in seconds;
  • REQUIRED_AUDIENCE_IN_TOKEN_REQUEST (default to false): if audience is required in token request;
  • ACCEPTED_AUDIENCES: comma-separated list of audiences accepted by the service, if included in JWT aud claim;
  • OPENID_CONFIG_PATH: string representing the path to the file contaning the OpenId Connect Configuration.
  • REDIS_HOSTS (required): redis host with port (default Redis port is 6379);
  • REDIS_USERNAME (optional): the username to authenticate to Redis;
  • REDIS_PASSWORD (optional): the password to authenticate to Redis;
  • REDIS_MODE: defines the redis mode (normal or sentinel) (default: normal);
  • REDIS_TLS (optional): if true, enable the TLS connection to Redis. Default is false;
  • REDIS_TLS_CACERT (optional): the path to the CA of the Redis server, if it's not public (this is effective only if REDIS_TLS is set to true);
  • REDIS_MASTER_NAME: defines the redis master name (required when using sentinel mode);
  • CLOCK_SKEW_SECONDS: defines the skew seconds that will be used into the /token request to validate the iat and notBefore claims of the client_assertion and reduce client and server clocks misalignment

RSA Key Management

An RSA key is a type of asymmetric cryptographic key used in public-key cryptography. In an RSA key pair, there are two keys: a public key and a private key.
The public key can be freely distributed and is used to encrypt messages that can only be decrypted with the private key. The private key, on the other hand, is kept secret and is used to decrypt the messages that have been encrypted with the public key.

Creation

This service accepts a private RSA key to sign the generated JWT (JSON Web Token). Refer to the related section for an explanation on how to generate it.

Deploy key in the Kubernetes cluster

Configure the service volume from Console

In the Console, on the client-credentials service, add a new configuration of type secret named client-credential-private-key and set the mount path at /configs.
Once this is done, set the environment variable PRIVATE_RSA_KEY_FILE_PATH value to /configs/private.key to configure it correctly.

Deploy with mlp

If you use mlp, the Mia-Platform deploy cli, to release custom secrets add these lines to the mlp.yaml file in your project:

secrets:
- name: "client-credential-private-key"
when: "always"
data:
- from: "literal"
key: "private.key"
value: "{{PRIVATE_KEY}}"

If you use GitLab as CI tool, set the environment variable PRIVATE_KEY with the value of the private key (copy the value using pbcopy < private.key).

Configure the service volume manually

You should set the key as volume from secret in the client-credentials service.

This is an example to add a secret to a volume:

apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-pod
image: my-image
env:
- name: PRIVATE_RSA_KEY_FILE_PATH
value: /configs/private.key
volumeMounts:
- name: client-credential-private-key
mountPath: "/configs"
readOnly: true
volumes:
- name: client-credential-private-key
secret:
secretName: client-credentials-private-key

With this configuration the created pod will be mounted with the secret generated from file private.key; the mount path inside the container will be /configs/private.key. Make sure your configuration is correct by checking that this is the value you have set for PRIVATE_RSA_KEY_FILE_PATH environment variable.

Deploy directly in namespace

You should create the key as secret in kubernetes, using:

kubectl -n my-namespace create secret generic my-secret --from-file="~/private.key"

OpenID Configuration

To expose the OpenId discovery endpoint correctly you should provide the configuration using a config map. This file must contain the exact JSON that will then be sent as response.

apiVersion: v1
data:
config.json: '{ "issuer": "https://www.valid.url", ... }'
kind: ConfigMap
metadata:
name: client-credentials

Now you have to load the config map inside a volume and mount that volume, as follows:

apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-pod
image: my-image
env:
- name: OPENID_CONFIG_PATH
value: /openid/config.json
volumeMounts:
- name: openid-config-volume
mountPath: "/openid"
readOnly: true
volumes:
- name: openid-config-volume
configMap:
name: openid-config

Note: the custom configuration MUST contain at least every required field.

Required fields:

  • issuer
  • token_endpoint
  • jwks_uri
  • response_types_supported
  • subject_types_supported
  • id_token_signing_alg_values_supported

Reference: OpenId Connect Discovery.

Reference