如何通过 API 集成 keycloak 短信认证?

Posted

技术标签:

【中文标题】如何通过 API 集成 keycloak 短信认证?【英文标题】:How to integrate keycloak sms authentication by API? 【发布时间】:2021-01-30 18:11:50 【问题描述】:

我有一个使用自定义 KeycloakProvider 的 keycloak 服务器和 Laravel 应用程序:

public function loginByEmail(string $email, string $password): SsoTokens

    try 
        $data = $this->realmEndpoint->makeRequest(
            HttpClientProvider::METHOD_POST,
            self::KEYCLOAK_AUTH_URL,
            [
                'client_id' => config('services.keycloak.realm_client'),
                'client_secret' => config('services.keycloak.realm_secret'),
                'grant_type' => 'password',
                'username' => $email,
                'password' => $password,
                'scope' => 'openid'
            ]
        );
     catch (TransportUnauthorizedException $e) 
        throw new UnauthorizedException($e);
     catch (HttpClientException $e) 
        throw new TransportException($e);
    

    return $this->extractTokens($data);

现在我的目标是通过用户的手机号码设置基本的 SMS 身份验证。我找到了一些工具(1、2),但它们不提供 API,只提供 html 页面。 有解决办法吗?

【问题讨论】:

这能回答你的问题吗? SMS based OTP in keycloak is possible? @zaerymoghaddam 谢谢你,但事实并非如此。我在我的问题中指出了 nickpack 的包,它没有实现与之交互的 API。 【参考方案1】:

我找到了解决方案。 在不知道密码的情况下登录:

    发送短信; 通过代码确认电话号码; 获取目标用户的keycloak ID; 以有权impersonate的用户身份登录; 与目标用户交换令牌。

需要TOKEN_EXCHANGE keycloak 功能。

步骤 1-3 我使用 Laravel 实现,步骤 4-5 使用 Keycloak API:

public function loginByUserId(string $userId): SsoTokens
    
        try 
            $impersonatorData = $this->realmEndpoint->makeRequest(
                HttpClientProvider::METHOD_POST,
                self::KEYCLOAK_AUTH_URL,
                [
                    'client_id' => config('services.keycloak.realm_client'),
                    'client_secret' => config('services.keycloak.realm_secret'),
                    'grant_type' => 'password',
                    'username' => config('services.keycloak.admin_username'),
                    'password' => config('services.keycloak.admin_password'),
                    'scope' => 'openid',
                ]
            );

            $data = $this->realmEndpoint->makeRequest(
                HttpClientProvider::METHOD_POST,
                self::KEYCLOAK_AUTH_URL,
                [
                    'client_id' => config('services.keycloak.realm_client'),
                    'client_secret' => config('services.keycloak.realm_secret'),
                    'grant_type' => 'urn:ietf:params:oauth:grant-type:token-exchange',
                    'requested_subject' => $userId,
                    'subject_token' => $impersonatorData['access_token'],
                    'scope' => 'openid',
                ]
            );
         catch (TransportUnauthorizedException $e) 
            throw new UnauthorizedException($e);
         catch (HttpClientException $e) 
            throw new TransportException($e);
        

        return $this->extractTokens($data);
    

【讨论】:

以上是关于如何通过 API 集成 keycloak 短信认证?的主要内容,如果未能解决你的问题,请参考以下文章

使用 JAVA 通过 REST API 集成 Keycloak 时在 toRepresentation() 处获取 404

如何在没有登录页面的情况下将 Keycloak 与 Spring Boot(API) 集成

Keycloak集成三方身份提供者的注销流程

Springboot 集成keycloak admin-cli api

如何通过 API 在 keycloak 中忘记密码

与 Keycloak 身份验证插件集成时,无法从 rest 客户端调用 nuxeo rest api