Configuration du webhook en temps réel

Cette page explique comment configurer un webhook en temps réel permettant l'intégration avec DUO.

Avant de commencer

Vérifiez que vous avez obtenu le jeton d'accès de votre client d'API.

Procédure

Créez le webhook en temps réel à l'aide de l'exemple CURL suivant.

Dans l'exemple, remplacez les valeurs suivantes.
{{DUO API Hostname}}
API hostname à partir de votre configuration d'application d'API d'authentification du titulaire DUO.
{{DUO Integration key}}
Integration key à partir de votre configuration d'application d'API d'authentification du titulaire DUO.
{{tenant}}
Votre nom de titulaire Verify.
{{access token}}
Jeton d'accès obtenu à partir de la subvention de données d'identification client.

Exemple de webhook CURL

curl --location --request POST 'https://{{tenant}}/v1.0/webhooks-mgmt/' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer {{access token}}}}' \
--data-raw '{
    "name": "DUO MFA Provider",
    "type": "realtime",
    "urls": ["{{DUO API Hostname}}"],
    "authentication": {
        "type": "header",
        "header": {
            "values":[
                {
                    "key": "hdr_integration_key",
                    "value": "{{DUO Integration key}}"
                },
                {
                    "key": "hdr_signing_key",
                    "value": "{{DUO Secret key}}"
                }
            ]
        }
    },
    "resources": {
        "enrollments": {
            "suffix": "/auth/v2/preauth",
            "method": "POST",
            "transform": {
                "outgoing": "{\"body\":jsonToFormURLEncoded({\"username\":body.username}, true), \"skip_authentication\": true, \"header\": header.put(\"date\", formatTime(now, '\''02 Jan 06 15:04 -0700'\'')).put(\"content-type\", \"application/x-www-form-urlencoded\").put(\"accept\", \"application/json\").put(\"authorization\", \"Basic \" + joinStrings([authentication_header.hdr_integration_key, hmacSha1(joinStrings([formatTime(now, '\''02 Jan 06 15:04 -0700'\''),method.toUpper(), host, path.toLower(), jsonToFormURLEncoded({\"username\":body.username}, true)], \"\\n\"), authentication_header.hdr_signing_key)], \":\").base64Encode())}",
                "incoming": "{\"body\": has(body.response) && has(body.response.devices) ? body.response.devices.map(d, d.capabilities.filter(c, c != \"auto\").map(c, {\"id\": d.device, \"capability\": c == \"mobile_otp\" ? \"hotp\" : c == \"sms\" ? \"smsotp\" : c, \"attributes\": {\"deviceName\": has(d.name) ? d.name : \"\", \"deliveryAddress\": has(d.number) ? d.number : \"\", \"authExecutionFlow\": c == \"mobile_otp\" ? \"validate\" : c == \"push\" ? \"init_then_poll\" : \"init_then_validate\"}})).flatten() : []}"
            }
        },
        "initiate": {
            "suffix": "/auth/v2/auth",
            "method": "POST",
            "transform": {
                "outgoing": "{\"body\":jsonToFormURLEncoded({\"async\":\"1\", \"device\":body.id, \"factor\": body.capability == \"smsotp\" ? \"sms\" : body.capability, \"username\":body.attributes.username}, true), \"skip_authentication\": true, \"header\": header.put(\"date\", formatTime(now, '\''02 Jan 06 15:04 -0700'\'')).put(\"content-type\", \"application/x-www-form-urlencoded\").put(\"accept\", \"application/json\").put(\"authorization\", \"Basic \" + joinStrings([authentication_header.hdr_integration_key, hmacSha1(joinStrings([formatTime(now, '\''02 Jan 06 15:04 -0700'\''),method.toUpper(), host, path.toLower(), jsonToFormURLEncoded({\"async\":\"1\", \"device\":body.id, \"factor\": body.capability == \"smsotp\" ? \"sms\" : body.capability, \"username\":body.attributes.username}, true)], \"\\n\"), authentication_header.hdr_signing_key)], \":\").base64Encode())}",
                "incoming": "{\"body\": has(body.response) && has(body.response.txid) ? {\"transactionId\": body.response.txid, \"status\": \"PENDING\"} : {\"status\": \"FAILED\"}}"
            }
        },
        "validate": {
            "suffix": "/auth/v2/auth",
            "method": "POST",
            "transform": {
                "outgoing": "{\"body\":jsonToFormURLEncoded({\"factor\": \"passcode\", \"passcode\": body.attributes.passvalue, \"username\":body.attributes.username}, true), \"skip_authentication\": true, \"header\": header.put(\"date\", formatTime(now, '\''02 Jan 06 15:04 -0700'\'')).put(\"content-type\", \"application/x-www-form-urlencoded\").put(\"accept\", \"application/json\").put(\"authorization\", \"Basic \" + joinStrings([authentication_header.hdr_integration_key, hmacSha1(joinStrings([formatTime(now, '\''02 Jan 06 15:04 -0700'\''),method.toUpper(), host, path.toLower(), jsonToFormURLEncoded({\"factor\": \"passcode\", \"passcode\": body.attributes.passvalue, \"username\":body.attributes.username}, true)], \"\\n\"), authentication_header.hdr_signing_key)], \":\").base64Encode())}",
                "incoming": "{\"body\": has(body.response) && has(body.response.result) ? {\"status\": body.response.result == \"allow\" ? \"SUCCESS\" : \"FAILED\", \"attributes\": body.response} : {\"status\": \"FAILED\"}}"
            }
        },
        "hotp_1": {
            "suffix": "/auth/v2/auth",
            "method": "POST",
            "transform": {
                "outgoing": "{\"body\":jsonToFormURLEncoded({\"factor\": \"passcode\", \"passcode\": body.attributes.passvalue, \"username\":body.attributes.username}, true), \"skip_authentication\": true, \"header\": header.put(\"date\", formatTime(now, '\''02 Jan 06 15:04 -0700'\'')).put(\"content-type\", \"application/x-www-form-urlencoded\").put(\"accept\", \"application/json\").put(\"authorization\", \"Basic \" + joinStrings([authentication_header.hdr_integration_key, hmacSha1(joinStrings([formatTime(now, '\''02 Jan 06 15:04 -0700'\''),method.toUpper(), host, path.toLower(), jsonToFormURLEncoded({\"factor\": \"passcode\", \"passcode\": body.attributes.passvalue, \"username\":body.attributes.username}, true)], \"\\n\"), authentication_header.hdr_signing_key)], \":\").base64Encode())}",
                "incoming": "{\"body\": has(body.response) && has(body.response.result) ? {\"status\": body.response.result == \"allow\" ? \"SUCCESS\" : \"FAILED\", \"attributes\": body.response} : {\"status\": \"FAILED\"}}"
            }
        },
        "result": {
            "suffix": "/auth/v2/auth_status",
            "method": "GET",
            "transform": {
                "outgoing": "{\"query\": {\"txid\": body.transactionId}, \"skip_authentication\": true, \"header\": header.put(\"date\", formatTime(now, '\''02 Jan 06 15:04 -0700'\'')).put(\"content-type\", \"application/x-www-form-urlencoded\").put(\"accept\", \"application/json\").put(\"authorization\", \"Basic \" + joinStrings([authentication_header.hdr_integration_key, hmacSha1(joinStrings([formatTime(now, '\''02 Jan 06 15:04 -0700'\''),method.toUpper(), host, path.toLower(), jsonToFormURLEncoded({\"txid\": body.transactionId}, true)], \"\\n\"), authentication_header.hdr_signing_key)], \":\").base64Encode())}",
                "incoming": "{\"body\": has(body.response) && has(body.response.result) ? {\"status\": body.response.result == \"allow\" ? \"SUCCESS\" : body.response.result == \"waiting\" || (body.response.result == \"deny\" && body.response.status == \"sent\") ?\"PENDING\" : body.response.status == \"timeout\" ? \"TIMEOUT\" : \"FAILED\", \"attributes\": body.response} : {\"status\": \"FAILED\"}}"
            }
        }
    },
    "purpose": ["external_mfa"]
}'
Notez le id dans le corps de réponse du webhook créé. Il est nécessaire de configurer le fournisseur MFA externe DUO.