使用API登录到Keycloak

54

我有两个不同的应用程序:分别是 Application1Application2

  1. 我已经将Application2与 Keycloak 集成,可以使用 Keycloak 的登录页面登录到该应用程序。

  2. 现在我想要的是,如果我在没有 Keycloak 的情况下登录到我的 Application1,我应该能够调用一些 Keycloak 的 API 来登录到 Application2(而无需呈现 Keycloak 的登录页面)。

这可行吗?如果可以,怎么做呢?

任何帮助将不胜感激。

谢谢


2
请参考此链接[https://dev59.com/dVUM5IYBdhLWcg3wF9TZ#50181199]以获取更多帮助。 - Ankur Singhal
5个回答

60

您事实上正在要求用户相信应用程序1会安全地管理他们的Keycloak凭据。这并不推荐,因为:

  1. 如果用户被重定向到Keycloak输入他们的凭据,则可以实现更好的安全性。在理想的情况下,任何客户端应用程序都不应处理或访问用户凭据。
  2. 这违背了单点登录的目的,用户只需要为他们需要访问的第一个应用程序输入凭据(前提是他们的会话尚未过期)

但是,如果您控制并且可以信任应用程序1并且由于传统或其他原因需要执行此操作,则可以在Keycloak客户端定义中启用名为“Direct Access”的资源所有者凭据流,然后将用户的凭据作为form-urlencoded数据类型进行POST请求。

https://<keycloak-url>/auth/realms/<realm>/protocol/openid-connect/token

参数将是

grant_type=password
client_id=<Application1's client id>
client_secret=<the client secret>
username=<the username>
password=<the password>
scope=<space delimited list of scope requests>

如果凭据无效,则响应将是一个有效的JWT对象或4xx错误。


谢谢你,shonky。我已经成功从你提到的REST服务中获取了响应。我得到了访问令牌、刷新令牌和其他一些参数。但是,我仍然无法直接登录到keycloak服务器。我是否漏掉了什么? - Akhil Prajapati
以上的API将会提供给你一个访问令牌,你可以用它来调用你的应用程序2。如果你已经有了访问令牌并且收到了401错误,请检查你是否正确传递了它(Bearer AccessToken),如果是的话,请检查应用程序2端的日志。如果你收到了403错误,则问题可能出在角色和访问列表上。需要指出的是,以上方法将无法让你访问Keycloak服务器(如果你需要访问它,那么可能需要更详细地说明用例)。 - Anunay
2
如果您正在进行REST调用,则在授权标头中传递令牌:curl http://localhost:8080/service/secured -H "Authorization: bearer $TOKEN"请参阅获取令牌并调用服务 - Anunay
请问您能否看一下我的与Keycloak相关的问题 https://dev59.com/NK72oIgBc1ULPQZFyr--?谢谢。 - Honza Zidek
超酷的问题和答案!!它已经帮了很大的忙。我有完全相同的问题,我的应用程序2是grafana。它可以通过重定向到keycloak登录页面进行登录。现在我想知道是否有一些keycloak端点应用程序1可以在幕后使用,以便用户可以直接进入grafana而无需访问keycloak登录页面?使用grant_type=password的令牌端点接收到的令牌似乎不被grafana信任。 - user1386058
显示剩余5条评论

7
如果我正确理解了您的问题,您正在尝试通过已经登录的另一个应用程序调用仅限承载者服务,您也没有提到您是否使用Spring Boot或类似的框架,因此我假设您正在使用Spring Boot作为您的服务器端应用程序。
以下示例反映了对另一个已验证API的简单调用,两者都使用Spring Boot:
import org.keycloak.KeycloakPrincipal;
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
import org.keycloak.adapters.springsecurity.account.SimpleKeycloakAccount;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;

@Component
public class AnotherServiceClient {
    public TypeOfObjectReturnedByAnotherService getFromAnotherService() {
        RestTemplate restTemplate = new RestTemplate();
        String endpoint = "http://localhost:40030/another/service/url";
        String bearerToken = getAuthorizationToken();

        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", "bearer " + bearerToken);

        HttpEntity entity = new HttpEntity(headers);

        ResponseEntity<TypeOfObjectReturnedByAnotherService> response = restTemplate.exchange(endpoint, HttpMethod.GET, entity, TypeOfObjectReturnedByAnotherService.class);

        return response.getBody();
    }

    private String getAuthorizationToken() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        SimpleKeycloakAccount details = (SimpleKeycloakAccount) authentication.getDetails();

        KeycloakPrincipal<?> keycloakPrincipal = (KeycloakPrincipal<?>) details.getPrincipal();

        RefreshableKeycloakSecurityContext context = (RefreshableKeycloakSecurityContext) getPrincipal().getKeycloakSecurityContext();

        return context.getTokenString();
    }
}

通过这种方式,可以将原始服务生成的实际有效令牌发送到另一个服务。

2
是的 - 您可以在不使用keycloak登录界面的情况下登录 Application-1 。有多种客户端适配器可用于实现此目的。这里没有提到您的应用程序框架。
要了解有关keyclaok客户端适配器的更多信息:单击此处 例如,如果您选择Node.js适配器,则可以按照以下链接进行操作:node.js适配器 在此链接中详细介绍了使用node.js适配器的keycloak实现,以及有关REST api和令牌验证机制的详细信息:单击此处查看示例

我正在使用Java。 - Akhil Prajapati

0
我已经开始使用Keycloak,并通过URL进行身份验证,我通过Python客户端以以下方式实现了这一点:
class KeyCloakAuthView(
    viewsets.GenericViewSet,
    mixins.CreateModelMixin,
):

    def create(self, request, *args, **kwargs):
        headers = {
            'Content-type': 'application/x-www-form-urlencoded',
        }
        payload = {
            "client_id": settings.KEYCLOAK_CLIENT_ID,
            "client_secret": settings.KEYCLOAK_CLIENT_SECRET,
            "scope": settings.KEYCLOAK_SCOPE,
            "grant_type": settings.KEYCLOAK_GRANT_TYPE,
            "username": "<username>",
            "password": "<passwd>",
        }
        rsp = requests.post(
            settings.KEYCLOAK_AUTH_URL,
            headers=headers,
            data=payload,
        )
        return Response(
            rsp.json(), status=status.HTTP_201_CREATED,
        )

论据:
KEYCLOAK_REALM = '<realm>'
KEYCLOAK_GRANT_TYPE = 'password'
KEYCLOAK_SCOPE = 'openid'
KEYCLOAK_CLIENT_ID = '<client-id>'
KEYCLOAK_CLIENT_SECRET = '<client-secret>'
KEYCLOAK_AUTH_URL = f"http://localhost:8080/realms/{KEYCLOAK_REALM}/protocol/openid-connect/token"

希望所提供的信息对任何人都有帮助。

0
Application2中,您使用了一种称为授权码授权的授权类型;它是由OAuth框架指定的几种授权类型之一。 Application1可以获得访问令牌的方法称为密码授权,除非您信任您的应用程序,否则不建议使用此授权。
您可以在这里了解正确使用keycloak与JavaScript应用程序集成的不同策略。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接