访问Keycloak返回的用户Oauth令牌

时间:2016-05-16 15:30:47

标签: jsf-2.2 twitter4j keycloak

我在AWS实例上使用Wildfly 10进行了Keycloak(独立)v1.9.4.Final安装设置,并尝试使用keycloak(通过keycloak的登录页面)和Twitter4j来通过Twitter对用户进行身份验证显然我的应用程序验证并查看用户时间表等。

我已经配置了身份提供商(Twitter),领域和我的客户端应用程序。

我还在apps.twitter.com上安装了Twitter应用程序,并将密钥放入我的twitter4j.properties文件中。

到目前为止,我能够:

  1. 转到我的应用程序的JSF网页,然后重定向到Keycloak&auth登录页面
  2. 点击Twitter徽标并使用我的Twitter帐户登录(与拥有Twitter应用程序的帐户分开的帐户)
  3. 填写Keycloak要求的用户信息
  4. 完成用户信息后,Keycloak成功地将用户引导回客户端应用程序(在本例中为JSF页面)。
  5. 问题是,我无法弄清楚如何访问用户OAuth AccessToken和AccessTokenSecret以与Twitter应用程序的ConsumerKey和ConsumerKeySecret结合使用。

    以下是代码的相关摘要:

    twitterLogin.xhtml

    ...
    #{twitterBean.getUserInfo()}
    ...
    


    TwitterBean.java

    @Context
    private final FacesContext facesContext = FacesContext.getCurrentInstance();
    private final Twitter twitter = TwitterFactory.getSingleton();
    
    public String getUserInfo() {
    
        if (facesContext != null) {
            HttpSession httpSession = (HttpSession) facesContext.getExternalContext().getSession(false);
            KeycloakSecurityContext keycloakContext = (RefreshableKeycloakSecurityContext) httpSession.getAttribute(KeycloakSecurityContext.class.getName());
            queryTwitter(keycloakContext.getTokenString(), keycloakContext.getIdTokenString());
        }
    }
    
    public void queryTwitter(String accessToken, String accessTokenSecret) {
        ConfigurationBuilder cb = new ConfigurationBuilder();
        cb.setDebugEnabled(true)
                .setOAuthConsumerKey("APPLICATIONS_CONSUMER_KEY")
                .setOAuthConsumerSecret("APPLICATIONS_CONSUMER_KEY_SECRET")
                .setOAuthAccessToken(accessToken)
                .setOAuthAccessTokenSecret(accessTokenSecret);
        TwitterFactory tf = new TwitterFactory(cb.build());
        twitter = tf.getInstance();
        user = twitter.verifyCredentials();
        ...
    }
    

    根据我们如何安排各种令牌(在不同的地方尝试不同的令牌字符串),我们会在调用verifyCredentials()时获得Twitter返回的不同错误,但所有基本上都是"无效的身份验证"。

    对我们来说很明显,.getTokenString()和.getIdTokenString()方法不是正确使用的方法,但我们不知道Keycloak会为用户提供哪些方法。 s oauth令牌。

    我们试图查看facesContext.getExternalContext()。getRequest()和facesContext.getExternalContext()。getResponse(),但没有太多运气。

    我的问题是,当用户通过Twitter进行身份验证并在Keycloak中注册用户后,Keycloak会重定向回客户端应用程序(服务提供商),保留了oauth令牌,以便我们可以访问它们然后进行双重身份验证(申请/用户认证)?

1 个答案:

答案 0 :(得分:2)

希望此代码段可以帮助某人......

@PostConstruct
public void init() {
    facesContext = FacesContext.getCurrentInstance();
}


public void login() {

    if (user == null) {

        if (facesContext != null) {
            HttpSession httpSession = (HttpSession) facesContext.getExternalContext().getSession(false);
            KeycloakSecurityContext keycloakContext = (RefreshableKeycloakSecurityContext) httpSession.getAttribute(KeycloakSecurityContext.class.getName());
            MyAccessToken accessToken = generateMyAccessToken(keycloakContext);

        }
    }
}

private MyAccessToken generateMyAccessToken(KeycloakSecurityContext keycloakContext) {
    AccessToken keycloakToken = keycloakContext.getToken();
    MyAccessToken token = new MyAccessToken();

    token.withEmail(keycloakToken.getEmail())
            .withExpiration(keycloakToken.getExpiration())
            .withUsername(keycloakToken.getPreferredUsername())
            .withOauthToken(getTwitterOAuthResponse(keycloakContext.getTokenString()))
            .withFirstName(keycloakToken.getGivenName())
            .withLastName(keycloakToken.getFamilyName());

    return token;
}

private OAuthTokenWrapper getTwitterOAuthResponse(final String tokenString) {
    ClientRequestFilter authFilter = new ClientRequestFilter() {
        @Override
        public void filter(ClientRequestContext requestContext) throws IOException {
            requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, "Bearer " + tokenString);
        }
    };

    Client client = ClientBuilder.newBuilder().register(authFilter).build();
    WebTarget target = client.target(getIdentityProviderTokenUrl());

    TwitterOAuthResponse resp = target.request().get().readEntity(TwitterOAuthResponse.class);
    return new OAuthTokenWrapper(resp.getToken(), resp.getTokenSecret());
}

private String getIdentityProviderTokenUrl() {
    return "https://login.example.com:8443/auth/realms/myapp/broker/twitter/token";

}