PowerFlex: Setting up PowerFlex single sign-on with Microsoft Azure using OpenID Connect (OIDC)

Summary: This article walks you through configuring PowerFlex Customer Identity and Access Management (CIAM) for SSO with Microsoft Azure Entra ID using OIDC.

This article applies to This article does not apply to This article is not tied to any specific product. Not all product versions are identified in this article.

Instructions

This article walks you through configuring PowerFlex Customer Identity and Access Management (CIAM) for SSO with Microsoft Azure Entra ID using OIDC, including certificate setup, IdP and service provider (SP) configuration, token exchange, and API access validation. This configuration makes it possible for you to take advantage of SSO capabilities. It requires configuration changes on both PowerFlex and Microsoft Azure.

This article is intended for administrators and security personnel using PowerFlex.

PowerFlex CIAM integrates with OIDC-compliant IdPs, including Microsoft Azure Entra ID, to enable centralized authentication and secure API access.

This article provides a step-by-step process to set up PowerFlex single sign-on with Microsoft Azure through the REST API. Here is the list of high-level steps:

  1. Initialize CIAM and configure PowerFlex as an OIDC Service Provider (SP)
  2. Register Microsoft Azure Entra ID as an OIDC Identity Provider (IdP)
  3. Add the required CA certificates (DigiCert/GlobalSign) to CIAM
  4. Configure Microsoft Azure application claims, redirect URIs, and permissions
  5. Create CIAM OAuth2 clients and token exchange mappings
  6. Obtain a Microsoft Azure token, exchange it for a PowerFlex token, and validate REST API access

Terminology

The following table describes important terms and concepts needed to complete this process:

Term Description
Management virtual machine (MVM) IP address The MVM IP addresses hosting PowerFlex Manager and management services. One MVM storage data server (SDS) node You can find the MVM IP addresses, by logging into the PowerFlex Manager user interface. Go to System->Components>MVM.  For example, 10.2xx.3xx.184, 10.2xx.3xx.185, 10.2xx.3xx.186
Storage data server (SDS) The storage data server (SDS) node that is hosting the MVMs.
Ingress IP address The external IP for rke2-ingress-nginx-controller (load balancer/ingress endpoint)
Customer Identity and Access Management (CIAM) The PowerFlex Customer Identity and Access Management services for OAuth2/OIDC
Service provider (SP) Identity provider (IdP)|The service provider (PowerFlex/Keycloak side) and the identity provider (Microsoft Azure Entra ID)

 

Prerequisites

There is an automation script (oidc_azure.tar) that is used for connecting Microsoft Azure Entra ID with PowerFlex.

The script is in a tar file format and must be downloaded and copied to your MVM:

To copy the oidc_azure. tar file, you must have administrative access to the PowerFlex management virtual machine.

Here is the file:   oidc_azure.tar

You must run the commands in the screen capture below because the variables that are exported are reused across the steps and scripts in this process.

Note: If you see permission errors, open a root login shell by running: sudo -i

 

What each command do?

  • The `kubectl get svc -A | grep "sso " | awk '{print $4}'`command returns the cluster IP address of the SSO service in the Kubernetes cluster.
  • The `curl -k --location --request POST "https://${SSO_IP}:8080/rest/auth/login" --header 'Accept: application/json' --header 'Content-Type: application/json' --data '{"username": "admin","password": "Scaleio123!" }' | jq -r .access_tokencommand logs into PowerFlex using the SSO REST API and retrieves an access token (JWT) that is used for subsequent API calls to PowerFlex services.
  • The`kubectl get svc -A | grep -m1 rke2-ingress-nginx-controller | sort | awk '{print $5}'`command returns the external IP address of the rke2-ingress-nginx-controller service, which is typically the load balancer or ingress controller IP used for external traffic.

 

When these commands are run, the following variables are exported:

export SSO_IP=$(kubectl get svc -A | grep "sso " | awk '{print $4}') 
export ASMUI_PASS=$(kubectl get secret pfxm-asmui-creds -o json -n powerflex \   | jq '.data | map_values(@base64d)' \   | jq -r '.["keycloak-password"]') 
export PM_TOKEN=$(curl -k --location --request POST "https://${SSO_IP}:8080/rest/auth/login" \   --header 'Accept: application/json' \   --header 'Content-Type: application/json' \   --data "{\"username\": \"asmuiuser\",\"password\": \"$ASMUI_PASS\"}" | jq -r .access_token) 
export IN_IP=$(kubectl get svc -A | grep -m1 rke2-ingress-nginx-controller | sort | awk '{print $5}')

 

 

1. Initialize CIAM and configure PowerFlex as an OIDC Service Provider (SP)

This step is the starting point in the process of integrating CIAM with PowerFlex using OpenID Connect (OICD). The SSO CIAM configuration for PowerFlex is initialized.

APIPOST /rest/v1/sso-ciam/init

Command: 

 
curl -k -X POST https://$IN_IP/rest/v1/sso-ciam/init --header 'Accept: application/json' --header 'Content-Type: application/json' --header "Authorization: Bearer ${PM_TOKEN}"

Script:  ./init.sh

Output: An integer, the CIAM tenant ID i.e. "2"

 

2. Configure PowerFlex with Keycloak as the OIDC Service provider.

This step registers and configures PowerFlex as an OIDC Service Provider with Keycloak (or another IdP), enabling secure SSO authentication using OpenID Connect.

API operation: POST /rest/v1/oidc-sp-config

Command:

curl -kL -X POST --url https://$IN_IP/rest/v1/oidc-sp-config  --header 'Content-Type: application/json' --header "Authorization: Bearer ${PM_TOKEN}" --data '{
  "sp_id": "powerflex-$IN_IP",
  "redirect_uri": "https://$IN_IP/auth/realms/powerflex/protocol/openid-connect/auth",
  "logout_uri": "https://$IN_IP/auth/realms/powerflex/protocol/openid-connect/logout",
  "required_claims": ["email"],
  "keycloak_settings": {
    "config": {
      "clientAuthMethod": "client_secret_basic",
      "pkceEnabled": "true",
      "useJwksUrl": "true",
      "validateSignature": "true"
    },
    "first_broker_login_flow_alias": "first broker login",
    "post_broker_login_flow_alias": null,
    "link_only": null,
    "store_token": true,
    "add_read_token_role_on_create": true,
    "trust_email": true
  },
  "days_to_store_state_code_verifier": 1}'

Script:  ./add_oidc_sp.sh

Output (truncated): New service provider

 
{"id":"00000000-0000-0000-0000-000000000000","sp_id":"powerflex-10.247.39.179","redirect_uris":["https://10.247.39.179/auth/realms/powerflex/protocol/openid-connect/auth"],"logout_uri":"https://10.247.39.179/auth/realms/powerflex/protocol/openid-connect/logout" ... },

 

2.1 List the OIDC service provider.

This step retrieves the current OIDC service provider configuration from PowerFlex,

Command:

curl -kL https://$IN_IP/rest/v1/oidc-sp-config --header 'Content-Type: application/json' --header "Authorization: Bearer ${PM_TOKEN}" | jq -r '.results[]'

Script: ./list_oidc_sp.sh

Sample output (truncated): A service provider created at the previous step.

{"results":[{"id":"00000000-0000-0000-0000-000000000000","sp_id":"powerflex-10.247.39.179",...}]

 

3. Add the certificate authority to PowerFlex for CIAM services.

This step involves informing PowerFlex about which certificate authority it should trust when validating secure communication with the CIAM system. There are two certificates for CIAM services:

  • DigiCert is a trusted Certificate Authority (CA). Microsoft Azure services (like Microsoft Azure AD, OIDC endpoints, and Microsoft APIs) use SSL/TLS certificates issued by DigiCert to secure communication.
  • GA2 (GlobalSign or similar root/intermediate) certificates are part of the certificate chain that validates Microsoft Azure’s identity endpoints. They ensure:
    • The OIDC metadata URL (https://login.microsoftonline.com/...)(External Link) and token endpoints are trusted.
    • Secure HTTPS communication between PowerFlex and Microsoft Azure IdP.

This operation ensures CIAM trusts Microsoft Azure endpoints.

The command below uses files with PEM encoded certificates, where new lines are replaced with "\n". Basically, there is only one line in such file.

For example:

 
-----BEGIN CERTIFICATE-----
\nMIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh\nMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\nd3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\nQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT\nMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\nb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG\n9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB\nCSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97\nnh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt\n43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P\nT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4\ngdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO\nBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR\nTLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw\nDQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr\nhMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg\n06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF\nPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls\nYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk\nCAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=\n-
----END CERTIFICATE-----

API: POST /Api/V1/CIAM/<ciam_id>/x509-certificates

Command:

CA=`cat $1`
curl -kvvL -X POST https://$IN_IP//Api/V1/CIAM/<return_value_from_init_ciam>/x509-certificates --header "Authorization: Bearer ${PM_TOKEN}" --data-raw "
{
  \"type\": \"CA\",
  \"service\": \"ALL\",
  \"certificate_format\": \"PEM\",
  \"certificate\": \"$CA\"
}"
Note: https://$IN_IP//Api/V1/CIAM/2/x509-certificate - here is the number 2 from the output of init.sh in step 1.

 

Script: ./add_cert.sh <certificate_pem_file>

Sample output (truncated):

cat digicert_ca.pem
-----BEGIN CERTIFICATE-----\nMIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh\nMQs;wCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\nd3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\nQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT\nMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\nb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG\n9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB\nCSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97\nnh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt\n43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P\nT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4\ngdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO\nBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR\nTLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw\nDQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr\nhMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg\n06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF\nPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls\nYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4p
...
Fsiv9kuXclVzDAGySj4dzp30d8tbQk\nCAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=\n-----END CERTIFICATE-----\n


delladmin@lglou184:~/oidc_testing> cat digicert_g2.pem
-----BEGIN CERTIFICATE-----\nMIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh\nMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\nd3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH\nMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT\nMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\nb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG\n9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI\n2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx\n1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ\nq2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz\ntCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ\nvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP\nBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV\n5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY\n1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4\nNeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG\nFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91\n8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe\npLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl\nMrY=\n-----END CERTIFICATE-----\n
--------------------------------------------------------------------------------------------------------------------------
./add_cert.sh digicert_ca.pem
{"id":"b5c3d51a-9161-4515-a741-4a197a348cf9","certificate":"-----BEGIN CERTIFICATE-----...\nMIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh\nMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\nd3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\nQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT\nMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\nb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG\n9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB\nCSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97\nnh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt\n43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P\nT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4\ngdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO\nBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR\nTLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw\nDQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr\nhMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg\n06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF\nPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls\nYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk\nCAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=\n-----END CERTIFICATE-----\n","subject":"C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root CA","common_name":"DigiCert Global Root CA","issuer":"C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root CA","organization":"DigiCert Inc","organizational_unit":"www.digicert.com","country":"US","valid_from_timestamp":"2006-11-10T00:00:00Z","valid_to_timestamp":"2031-11-10T00:00:00Z","key_usage":"Digital Signature, Cert Sign, CRL Sign","type":"CA","service":"ALL","is_self_signed":true,"is_current":true,"is_valid":true,"cert_fingerprint":"43:48:A0:E9:44:4C:78:CB:26:5E:05:8D:5E:89:44:B4:D8:4F:96:62:BD:26:DB:25:7F:89:34:A4:43:C7:* Connection #0 to host 10.247.39.179 left intact
01:61","version":3,"serial_number":10944719598952040374951832963794454346,"signature_algorithm":"RSA","signature_hash_algorithm":"SHA-1","public_key":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKP\nC3eQyaKl7hLOllsBCSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtx\nRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmF\naG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvU\nX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrT\nC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOv\nJwIDAQAB\n-----END PUBLIC KEY-----\n"}

 

 3.1 Verify the certificates are added and listed.

This step verifies that the certificates are add and listed.

Command:

 
curl -kL https://$IN_IP/Api/V1/CIAM/2/x509-certificates --header 'Content-Type: application/json' --header "Authorization: Bearer ${PM_TOKEN}"

Note: https://$IN_IP//Api/V1/CIAM/2/x509-certificate - here is the number 2 from the init.sh in step 1.

Script: ./list_certs.sh

Sample output (truncated):

{"results":[{"id":"4a4d7f6b-251c-41a6-b304-783ed6d5fbc2","certificate":"-----BEGIN ....-----END PUBLIC KEY-----\n"}]}

 

4. Register Microsoft Azure Entra ID as the OIDC Service (IdP)

This step registers Microsoft Azure Entra ID as an external identity provider for PowerFlex using OpenID Connect (OIDC), enabling users to authenticate through Microsoft Azure rather than relying on local PowerFlex credentials.

Variables:

  • Tenant ID: The Tenant ID identifies the Microsoft Azure Active Directory tenant to which the identity provider belongs. You can find it on the Overview page of the application's home screen in Microsoft Azure.
  • KK_ID: The KK ID identifies the client ID of the Microsoft Azure application.
  • KK_SECRET: The KK secret identifies the client secret of Microsoft Azure.

API: POST /rest/v1/oidc-services

 
curl -kvvL --request POST \
--url "https://$IN_IP/rest/v1/oidc-services" \
--header 'Content-Type: application/json' \
--header "Authorization: Bearer ${PM_TOKEN}" \
--data "{
\"name\": \"azure\",
\"is_enabled\": true,
\"idp_metadata_url\": \"https://login.microsoftonline.com/<Tenant_id>/v2.0/.well-known/openid-configuration\",
\"claims_mapper\": [
{ \"name\": \"email\", \"value\": \"email\" },
{ \"name\": \"given_name\", \"value\": \"firstName\" },
{ \"name\": \"preferred_username\", \"value\": \"username\" },
{ \"name\": \"family_name\", \"value\": \"lastName\" }
],
\"client_id\": \"$KK_ID\",
\"client_secret\": \"$KK_SECRET\",
\"scopes\": [\"openid\",\"profile\",\"email\",\"offline_access\"],
\"pkce_enabled\": true,
\"code_challenge_method\": \"S256\",
\"idp \"idp_type\": \"AzureEntraID\"KK_ID=b151947c-b514-4997-a369-a9b76f26b050
KK_SECRET=tk_8Q~QYTj1FQYN2chWovu.M5Ph3YnIVzLwRJcoZ
TENANT_ID=945c199a-83a2-4e80-9f8c-5a91be5752dd

curl -kL -X POST  --url https://$IN_IP/rest/v1/oidc-services  --header 'Content-Type: application/json'  --header "Authorization: Bearer ${PM_TOKEN}" \
  --data  \
"{  \"name\": \"azure\",  \"is_enabled\": true,  \"idp_metadata_url\": \"https://login.microsoftonline.com/${TENANT_ID}/v2.0/.well-known/openid-configuration\",
  \"claims_mapper\": [    {      \"name\": \"email\",      \"value\": \"email\"
    },
    {
      \"name\": \"given_name\",
      \"value\": \"firstName\"
    },
    {
      \"name\": \"preferred_username\",
      \"value\": \"username\"
    },
    {
      \"name\": \"family_name\",
      \"value\": \"lastName\"
    }
  ],
  \"client_id\": \"$KK_ID\",
  \"client_secret\": \"$KK_SECRET\",
  \"scopes\": [
    \"openid\",
    \"profile\",
    \"email\",
    \"offline_access\" 
  ],
  \"pkce_enabled\": true,
  \"code_challenge_method\": \"S256\",
  \"idp_type\": \"AzureEntraID\"
}"

 Script: ./add_oidc_service.sh

Sample output (truncated):

{
  "id": "a230b7b8-8f6c-47db-9327-2e48db8040a9",
  "name": "azure",
  "is_enabled": true,
  "idp_metadata_url": "https://login.microsoftonline.com/945c199a-83a2-4e80-9f8c-5a91be5752dd/v2.0/.well-known/openid-configuration",
  "idp_metadata_load_timestamp": "2025-11-14T16:00:40.356569216Z",
  "idp_metadata": {
    "issuer": "https://login.microsoftonline.com/945c199a-83a2-4e80-9f8c-5a91be5752dd/v2.0",
    "...": "additional metadata fields"
  },
  "code_challenge_method": "S256",
  "idp_type": "AzureEntraID",
  "is_default": false
}
 Important:  You must save the OIDC service ID from the response (e.g., a230b7b8-...); you will need it for Microsoft Azure redirect URI and CIAM token exchange mapping.

 

 

4.1 List the OIDC service.

This step lists the OIDC service.

Command:

curl -kL https://$IN_IP/rest/v1/oidc-services --header 'Content-Type: application/json' --header "Authorization: Bearer ${PM_TOKEN}"

 Script: list_oidc_service.sh 

Example (truncated):

./list_oidc_service.sh 
{"results":[{"id":"a230b7b8-8f6c-47db-9327-2e48db8040a9","name":"azure","is_enabled":true,"idp_metadata_url":"https://login.microsoftonline.com/945c199a-83a2-4e80-9f8c-5a91be5752dd/v2.0/.well-known/openid-configuration",..."idp_type":"AzureEntraID","is_default":false}]}

 

5. Configure the redirect URL in Microsoft Azure.

This step involves setting up Microsoft Azure to send users to a destination called a redirect URL after they successfully sign in.

In the Microsoft Azure Portal, go to App Registration → Authentication → Redirect URIs, and add the following URL:

https://<PFMP_IP>/auth/realms/powerflex/broker/<SERVICE_ID_AZURE>/endpoint

For examplehttps://10.247.39.179/auth/realms/powerflex/broker/a230b7b8-8f6c-47db-9327-2e48db8040a9/endpoint

  • <PFMP_IP> is the PowerFlex Manager IP (if required, resolve hostname)
  • <SERVICE_ID_AZURE> is the IdP from the service ID from Step 4.

 

6. Configure the token claims in Microsoft Azure.

a) Add optional claims (ID Token)

  1. In the Microsoft Azure Portal, go to Token configuration → Add optional claim.
  2. Under Token type, select ID.
  3. Under Claim, select the checkbox beside the following attributes:
    • email

    • family_name

    • given_name

    • preferred_username

  4. Click Add.

 

 b) Add group claims

  1. In the Microsoft Azure Portal, go to Token configuration → Add group claims.           
  2. Under Edit groups claim, select the checkbox beside Groups assigned to application.   
  3. Under ID, select the checkbox beside Group ID.                                                                   
  4. Under Access, select the checkbox beside Group ID.                                                             
  5. Click Add.

You will use these group IDs later for PowerFlex role mapping in the PowerFlex Manager user interface.

 

7. Configure API permissions in Microsoft Azure.

This step ensures that PowerFlex has the correct access to protected resources in Microsoft Azure.

  1. In the Microsoft Azure Portal, go to API permissions Microsoft Graph.
  2. Under Request API permissions, select
  3. Under Request API permissions, select User → Read.
  4. Click Update permissions.

 

8. (Optional) Assign users/groups in Microsoft Azure.

This step grants the appropriate individuals or teams access to PowerFlex by assigning them to specific roles or groups within Microsoft Azure Active Directory.

  1. In the Microsoft Azure Portal, go to Enterprise applications → Users and groups.
  2. Under Display name, select the checkbox beside the user/group and copy the object ID.

The object ID is used for claims-based role mapping in PowerFlex.

 

9. (Optional) Add the user/group in the PowerFlex user interface

This step involves granting access within PowerFlex by adding the appropriate user or group directly in the PowerFlex Manager user, ensuring they can log in and use the system according to their assigned roles and permissions.

  1. Log in to the PowerFlex Manager user interface.
  2. Go to Settings → User management → Add Remote User/Group.
  3. Enter the following information:
    1. Type: group
    2. Provider: Azure
    3. Group name: any meaningful name
    4. Claim Name: groups
    5. User role: Super User
    6. Claim Value: Object ID from Microsoft Azure (Step 8)

10. Add the client to CIAM.

This step adds the client to CIAM to register PowerFlex so CIAM can determine what application is requesting authentication, where to send tokens, what permissions the application needs, and which authentication flows it can use.

API: POST /rest/v1/oauth2-clients

Command:

curl -kL --request POST \
--url "https://$IN_IP/rest/v1/oauth2-clients" \
--header 'Content-Type: application/json' \
--header "Authorization: Bearer ${PM_TOKEN}" \
--data "{
\"client_name\": \"azure_oidc_client\",
\"redirect_uris\": [\"\"],
\"authorization_code_flow\": false,
\"client_credentials_flow\": false,
\"token_exchange_enabled\": true,
\"offline_access_enabled\": true,
\"client_offline_session_idle\": 1,
\"client_offline_session_max\": 1,
\"client_security_level\": \"TRUSTED\"

Script: ./addclient_ciam.sh

Example output:

./addclient_ciam.sh 
{"id":"77ce10cb-c40e-4c1e-b922-07014b5b6e7b","client_name":"azure_oidc_client","client_secret":"QXDtyVYO5l3Puj2ZMACz/MK+sTSOqDHy53oRhVkXiBc=","redirect_uris":[""],"authorization_code_flow":false,"client_credentials_flow":false,"signing_algorithm":"RS256","refresh_token_max_reuse":3,"access_token_expiration_duration":360,"token_exchange_enabled":true,"client_security_level":"TRUSTED","offline_access_enabled":true,"client_offline_session_idle":1,"client_offline_session_max":1
Note: You must save the CIAM client id and client_secret because they are needed for token exchange between Microsoft Azure and PowerFlex.

 

 

10.1 Verify the client is added by listing it.

This step verifies that the client is successfully added by listing all the existing clients.

Command: 

curl -kL https://$IN_IP/rest/v1/oauth2-clients --header 'Content-Type: application/json' --header "Authorization: Bearer ${PM_TOKEN}" | jq -r '.results[]'

Script: ./list_clients_ciam.sh

Example:

./list_clients_ciam.sh
{
  "id": "77ce10cb-c40e-4c1e-b922-07014b5b6e7b",
  "client_name": "azure_oidc_client",
  "redirect_uris": [
    ""
  ],
  "authorization_code_flow": false,
  "client_credentials_flow": false,
  "signing_algorithm": "RS256",
  "refresh_token_max_reuse": 3,
  "access_token_expiration_duration": 360,
  "token_exchange_enabled": true,
  "client_security_level": "TRUSTED",
  "offline_access_enabled": true,
  "client_offline_session_idle": 1,
  "client_offline_session_max": 1,
  "num_failed_login_attempts": 0
}

 

10.2 Modify the client.

This step updates an existing login client in CIAM. The payload should remain empty ({}). This command adds PowerFlex required mappings to Keycloak client.

Command:

curl -k -X PATCH "https://$IN_IP/rest/v1/login-clients/$1" \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "Authorization: Bearer ${PM_TOKEN}" \
  --data '{}'

Script: ./update_client.sh <ID_FROM_ADD_CLIENT_CIAM>

Example:

 
./update_client.sh 77ce10cb-c40e-4c1e-b922-07014b5b6e7b 
{"id":"1c3dbd45-66bc-44c7-94ce-1aef3a282afc","name":"azure_oidc_client","client_id":"77ce10cb-c40e-4c1e-b922-07014b5b6e7b","is_enabled":true,"client_secret":null,"redirect_uris":[""],"web_origins":[""]}

 

11. Add the application to CIAM for token exchange mapping

This step adds the application to CIAM to enable external authentication, authorization, and secure identity flows.

API: POST /rest/v1/oauth2-token-exchanges

Required variables:

  • LOCAL_CLIENT_ID: ID from addclient_ciam.sh (e.g., 77ce10cb-c40e-4c1e-b922-07014b5b6e7b)
  • EXT_CLIENT_ID:      Microsoft Entra ID Application (client) ID (e.g., 859c0721-cb0c-433c-a437-bd2d2462754f)
  • METADATA:            Microsoft Azure application metadata URL (e.g., https://login.microsoftonline.com/<Tenant_id>/v2.0/.well-known/openid-configuration)
  • IDP:                        OIDC service ID (e.g., a230b7b8-8f6c-47db-9327-2e48db8040a9)
  • ROLE:                     PowerFlex role (e.g., SuperUser)
  • PM_TOKEN:           API bearer token
  • IN_IP:                     Target host/IP address


Command:

curl -kL -X POST "https://$IN_IP/rest/v1/oauth2-token-exchanges" \
  -H "Content-Type: application/json" \
  -H "clientId: $LOCAL_CLIENT_ID" \
  -H "Authorization: Bearer ${PM_TOKEN}" \
  --data @- <<EOF
{
  "ciam_oauth2_client_id": "$LOCAL_CLIENT_ID",
  "customer_client_id": "$EXT_CLIENT_ID",
  "customer_metadata_url": "$METADATA",
  "idp_service_id": "$IDP",
  "static_roles": ["$ROLE"]
}

Script: ./add_app.sh

 

11.1 List the application ID

This step retrieve the application ID to validate the unique client identifier required for downstream authorization and token‑exchange operations.

Command:

curl -kL "https://$IN_IP/rest/v1/oidc-services" \
  --header "Content-Type: application/json" \
  --header "Authorization: Bearer ${PM_TOKEN}"

 Script: 

 
./list_apps.sh

Example:

./list_apps.sh
 { "id": "f803da04-2979-49dc-9408-496f127639b4",
  "ciam_oauth2_client_id": "77ce10cb-c40e-4c1e-b922-07014b5b6e7b",
  "customer_client_id": "859c0721-cb0c-433c-a437-bd2d2462754f",
  "customer_metadata_url": "https://login.microsoftonline.com/945c199a-83a2-4e80-9f8c-5a91be5752dd/v2.0/.well-known/openid-configuration",
  "idp_service_id": "a230b7b8-8f6c-47db-9327-2e48db8040a9",
  "static_roles": [
    "SuperUser"  ]
}
Note: Make a note of this ID.

 

 

12. Map roles in Keycloak (PowerFlex Realm)

This step maps roles in the PowerFlex Keycloak realm to align identity provider role assignments with PowerFlex authorization requirements.

1. Log in to Keycloak using the following endpointhttps://<PFMP_IP>/auth/admin/

For example: https://10.247.39.179/auth/admin/

To log in to the Keycloak, the credentials can be retrieved as below 

Command:

kubectl get secret keycloak-admin-credentials -o json -n powerflex | jq '.data | map_values(@base64d)'

Script: ./get_keycloak_creds.sh

Example: 

./get_keycloak_creds.sh
{
  "password": "sZFmHmfhjj",
  "username": "keycloak"
}

2. In the Keycloak instance, select the PowerFlex.

3. Click on Users and select the user ID and update the attributes to match the role used in CIAM (for example, SuperUser).

4. Under Role mapping, verify that the role is updated.

 

13. Obtain the Microsoft Azure token (Resource Owner Password Credentials / username + password)

There are multiple ways to get a token from Microsoft Azure AD. In this step example, the application is logging in to Microsoft Entra ID (Azure AD) by directly submitting a user’s username + password to the token endpoint in order to receive an OAuth 2.0 token. This is the Resource Owner Password Credentials (ROPC) grant.

Command:

 
curl -X POST https://login.microsoftonline.com/$TENANT_ID/oauth2/token -H 'Content-Type: application/x-www-form-urlencoded' -d "grant_type=password&client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET&username=$USERNAME&password=$encoded_password&resource=$RESOURCE")

Script:./get_azure_token.sh

Tip: To ensure that the token is valid, go to the JSON Web Token (JWT) Debugger (External Link)

 

14. Exchange the Microsoft Azure token for the PowerFlex token (CIAM)

This step exchanges the Microsoft Azure token for a PowerFlex CIAM token so that the PowerFlex APIs can be called.

API: POST /rest/v1/token

Variables:

  • CIAM_CLIENT_ID - Client ID from Add the client to CIAM step (step 10)
  • CIAM_CLIENT_SECRET - Client secret from Add the client to CIAM step (step 10)
  • EXT_TOKEN - Token from Microsoft Azure

Command:

curl -kL -X POST https://$IN_IP/rest/v1/token \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --header "ClientId: $CIAM_CLIENT_ID" \
  --header "ClientSecret: $CIAM_CLIENT_SECRET" \
  --data "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
  --data "subject_token=${EXT_TOKEN}" \
  --data "subject_token_type=urn:ietf:params:oauth:token-type:jwt"

Scripts: ./token.sh (uses the EXT_TOKEN therefore set the environmental variable accordingly)

Example output (truncated):

{
  "access_token": "ey...A",
  "issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
  "token_type": "Bearer",
  "expires_in": 1800,
  "refresh_token": "ey...qA"
}

 

15. Verify access to the PowerFlex REST API

This step confirms that the token works by calling a PowerFlex REST endpoint. It uses the access_token from the output of the "token.sh", exported as env variable PM_TOKEN.

export PM_TOKEN=eyJhb...eN_A

Command:

curl -k --location --request GET https://$IN_IP/Api/V1/Credential --header 'Content-Type: application/json' --header "Authorization: Bearer $PM_TOKEN"
{
  "totalRecords" : 3,
  "credentialList" : [ {
    "link" : {
      "title" : "root",
      "href" : "getCredential/69087b0c-cce7-4be7-b154-e8a3019cc553",
      "rel" : "self",
      "type" : null
    },
    "credential" : {
      "type" : "OSCredential",
      "id" : "69087b0c-cce7-4be7-b154-e8a3019cc553",
     ....
 "link" : null,. "link" : null,. "link" : null,    "references" : {
      "devices" : 0,
      "policies" : 0
    }
  } ]
}

 

Reference information

Summary of API sequence

  1. Initialize CIAM for PowerFlex
    (/rest/v1/sso-ciam/init)
  2. Configure PowerFlex as OIDC service provider
    (/rest/v1/oidc-sp-config)
  3. Add certificates for CIAM Services
    (DigiCert, GlobalSign, etc.)
  4. Register Microsoft Azure Entra ID as OIDC Service
    (/rest/v1/oidc-services)
  5. Configure Service ID in Microsoft Azure Authentication tab
    (Broker endpoint mapping)
  6. Set token and group claims in Microsoft Azure
    (Optional claims, API permissions)
  7. Add OAuth2 client in CIAM
    (/rest/v1/oauth2-clients)
  8. Add application to CIAM for token exchange
    (/rest/v1/oauth2-token-exchanges)
  9. Obtain Microsoft Azure token to exchange for PowerFlex token
    (/rest/v1/token)
  10. Verify access to PowerFlex REST APIs

 

 

Commands to perform a token exchange

Calling PowerFlex APIs with Microsoft Azure Entra token


Command to perform a token exchange:

curl -kL -X POST https://$PFMP_IP/rest/v1/token \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --header "ClientId: $CIAM_CLIENT_ID" \
  --header "ClientSecret: $CIAM_CLIENT_SECRET" \
  --data "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
  --data "subject_token=${AZURE_TOKEN}" \
  --data "subject_token_type=urn:ietf:params:oauth:token-type:jwt" | jq '.'

Example:

curl -kL -X POST https://10.247.39.179/rest/v1/token \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --header "ClientId: 77ce10cb-c40e-4c1e-b922-07014b5b6e7b" \
  --header "ClientSecret: QXDtyVYO5l3Puj2ZMACz/MK+sTSOqDHy53oRhVkXiBc=" \
  --data "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
  --data "subject_token=${AZURE_TOKEN}" \
  --data "subject_token_type=urn:ietf:params:oauth:token-type:jwt" | jq '.'

Calling PowerFlex Manager Appliance API with exchanged token

curl -kL 'https://10.247.39.179/api/v1/appliance' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIzMkNrM2YwNEI5OG5pRENza19IVmZ3R..._dxDp9QGWdteptby-8aaA'

 

Calling PowerFlex Block API with exchanged token

curl -kL GET https://10.247.39.179/api/types/Volume/instances --header 'Content-Type: application/json' --header "Authorization: Bearer  eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIzMkNrM2YwNEI5OG5pRENza19IVmZ3R..._dxDp9QGWdteptby-8aaA " 
[
  {
    "genType": "EC",
    "mappedSdcInfo": [
      {
        "limitIops": null,
        "limitBwInMbps": null,
        "isDirectBufferMapping": null,
        "sdcIp": "",
        "sdcId": "15d47a2400010000",
        "sdcName": "513fda498aaf35e883da34f6ac46480",
        "nqn": "nqn.2014-08.org.nvmexpress:uuid:72f30442-1cf7-0f5b-129c-da4fae6a028b",
        "accessMode": "ReadWrite",
        "hostType": "NVMeHost"
      }
    ],
    "managedBy": "ScaleIO",
    "originalExpiryTime": 0,
    "retentionLevels": [],
    "snplIdOfSourceVolume": null,
    "volumeReplicationState": "UnmarkedForReplication",
    "replicationJournalVolume": false,
    "replicationTimeStamp": 0,
    "name": "csivol-21ef5b460c",
    "creationTime": 1763382058,
    "storagePoolId": "0ebdb61000000000",
    "dataLayout": "ErasureCoding",
    "vtreeId": "97957f7d00000002",
    "sizeInKb": 8388608,
    "compressionMethod": "NotApplicable",
    "volumeClass": "defaultclass",
    "accessModeLimit": "ReadWrite",
    "lockedAutoSnapshotMarkedForRemoval": false,
    "snplIdOfAutoSnapshot": null,
    "pairIds": null,
    "useRmcache": false,
    "volumeType": "ThinProvisioned",
    "consistencyGroupId": null,
    "ancestorVolumeId": null,
    "notGenuineSnapshot": false,
    "secureSnapshotExpTime": 0,
    "lockedAutoSnapshot": false,
    "autoSnapshotGroupId": null,
    "timeStampIsAccurate": false,
    "nsid": 3,
    "id": "77d698a400000002",
    "links": [
      {
        "rel": "self",
        "href": "/api/instances/Volume::77d698a400000002"
      },
      {
        "rel": "/dtapi/rest/v1/metrics/query",
        "href": "/dtapi/rest/v1/metrics/query",
        "body": {
          "resource_type": "volume",
          "ids": [
            "77d698a400000002"
          ]
        }
      },
      {
        "rel": "/api/parent/relationship/vtreeId",
        "href": "/api/instances/VTree::97957f7d00000002"
      },
      {
        "rel": "/api/parent/relationship/storagePoolId",
        "href": "/api/instances/StoragePool::0ebdb61000000000"
      }
    ]
  },
  {
    "genType": "EC",
    "mappedSdcInfo": null,
    "managedBy": "ScaleIO",
    "originalExpiryTime": 0,
    "retentionLevels": [],
    "snplIdOfSourceVolume": null,
    "volumeReplicationState": "UnmarkedForReplication",
    "replicationJournalVolume": false,
    "replicationTimeStamp": 0,
    "name": "csivol-4ea9633592",
    "creationTime": 1763380456,
    "storagePoolId": "0ebdb61000000000",
    "dataLayout": "ErasureCoding",
    "vtreeId": "9795586d00000000",
    "sizeInKb": 8388608,
    "compressionMethod": "NotApplicable",
    "volumeClass": "defaultclass",
    "accessModeLimit": "ReadWrite",
    "lockedAutoSnapshotMarkedForRemoval": false,
    "snplIdOfAutoSnapshot": null,
    "pairIds": null,
    "useRmcache": false,
    "volumeType": "ThinProvisioned",
    "consistencyGroupId": null,
    "ancestorVolumeId": null,
    "notGenuineSnapshot": false,
    "secureSnapshotExpTime": 0,
    "lockedAutoSnapshot": false,
    "autoSnapshotGroupId": null,
    "timeStampIsAccurate": false,
    "nsid": 1,
    "id": "77d6719400000000",
    "links": [
      {
        "rel": "self",
        "href": "/api/instances/Volume::77d6719400000000"
      },
      {
        "rel": "/dtapi/rest/v1/metrics/query",
        "href": "/dtapi/rest/v1/metrics/query",
        "body": {
          "resource_type": "volume",
          "ids": [
            "77d6719400000000"
          ]
    .
.
.
    ]
  }
]

Affected Products

PowerFlex rack, ScaleIO

Attachments

oidc.azure_pkb_en_US_1.tar

Article Properties
Article Number: 000444444
Article Type: How To
Last Modified: 14 نيسان 2026
Version:  4
Find answers to your questions from other Dell users
Support Services
Check if your device is covered by Support Services.