Skip to content

Commit

Permalink
add WeiXinIdentityBrokerService
Browse files Browse the repository at this point in the history
  • Loading branch information
ap-tianjef committed Jun 11, 2020
1 parent 858bc1e commit b409e3d
Show file tree
Hide file tree
Showing 8 changed files with 789 additions and 12 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services-social-weixin</artifactId>
<version>0.0.10</version>
<version>0.0.19</version>
<name>Keycloak Services Social WeiXin</name>
<description/>
<properties>
Expand Down
25 changes: 25 additions & 0 deletions src/main/java/org/keycloak/social/weixin/Util.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.keycloak.social.weixin;

import java.lang.reflect.Field;

public class Util {
public static String inspect(String varName, Object thing) {
StringBuilder sb = new StringBuilder();

sb.append(varName).append(" >>>").append("\n");
for (Field field : thing.getClass().getDeclaredFields()) {
field.setAccessible(true);
String name = field.getName();
Object value = null;
try {
value = field.get(thing);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
sb.append("\t").append(name).append(": ").append(value).append("\n");
}
sb.append(varName).append(" <<<").append("\n");

return sb.toString();
}
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;

import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.OAuth2Constants;
import org.keycloak.broker.oidc.AbstractOAuth2IdentityProvider;
import org.keycloak.broker.oidc.OAuth2IdentityProviderConfig;
Expand Down Expand Up @@ -199,6 +200,12 @@ protected UriBuilder createAuthorizationUrl(AuthenticationRequest request) {
if (customizedLoginUrlForPc != null && !customizedLoginUrlForPc.isEmpty()) {
uriBuilder = UriBuilder.fromUri(customizedLoginUrlForPc);

uriBuilder.queryParam(OAUTH2_PARAMETER_SCOPE, WECHAT_DEFAULT_SCOPE)
.queryParam(OAUTH2_PARAMETER_STATE, request.getState().getEncoded())
.queryParam(OAUTH2_PARAMETER_RESPONSE_TYPE, "code")
.queryParam(OAUTH2_PARAMETER_CLIENT_ID, getConfig().getConfig().get(WECHAT_APPID_KEY))
.queryParam(OAUTH2_PARAMETER_REDIRECT_URI, request.getRedirectUri());

return uriBuilder;
} else {
uriBuilder = UriBuilder.fromUri(getConfig().getAuthorizationUrl());
Expand Down Expand Up @@ -260,6 +267,9 @@ protected class Endpoint {
@Context
protected UriInfo uriInfo;

@Context
protected HttpRequest request;

public Endpoint(AuthenticationCallback callback, RealmModel realm, EventBuilder event) {
this.callback = callback;
this.realm = realm;
Expand Down Expand Up @@ -291,30 +301,44 @@ public Response authResponse(@QueryParam(AbstractOAuth2IdentityProvider.OAUTH2_P
BrokeredIdentityContext federatedIdentity;

if (openid != null) {
// TODO: use ticket here instead, and then use this ticket to get openid from sso.jiwai.win
federatedIdentity = customAuth.auth(openid);

return LoginWithFederatedIdentity(state, federatedIdentity, customAuth.accessToken);
setFederatedIdentity(state, federatedIdentity, customAuth.accessToken);

logger.info(Util.inspect("federatedIdentity", federatedIdentity));

WeiXinIdentityBrokerService weiXinIdentityBrokerService =
new WeiXinIdentityBrokerService(realm);
weiXinIdentityBrokerService.init(session, clientConnection, headers, event, request);

return weiXinIdentityBrokerService.authenticated(federatedIdentity);
// return callback.authenticated(federatedIdentity);
}

if (authorizationCode != null) {
String response = generateTokenRequest(authorizationCode, wechatFlag).asString();
logger.info("response=" + response);
federatedIdentity = getFederatedIdentity(response, wechatFlag);

return LoginWithFederatedIdentity(state, federatedIdentity, response);
setFederatedIdentity(state, federatedIdentity, response);

logger.info(Util.inspect("federatedIdentity", federatedIdentity));

return callback.authenticated(federatedIdentity);
}
} catch (WebApplicationException e) {
return e.getResponse();
} catch (Exception e) {
logger.error("Failed to make identity provider oauth callback", e);
logger.error("Failed to make identity provider (weixin) oauth callback", e);
}
event.event(EventType.LOGIN);
event.error(Errors.IDENTITY_PROVIDER_LOGIN_FAILURE);
return ErrorPage.error(session, null, Response.Status.BAD_GATEWAY,
Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
}

public Response LoginWithFederatedIdentity(@QueryParam(AbstractOAuth2IdentityProvider.OAUTH2_PARAMETER_STATE) String state, BrokeredIdentityContext federatedIdentity, String accessToken) {
public void setFederatedIdentity(@QueryParam(AbstractOAuth2IdentityProvider.OAUTH2_PARAMETER_STATE) String state, BrokeredIdentityContext federatedIdentity, String accessToken) {
if (getConfig().isStoreToken()) {
if (federatedIdentity.getToken() == null)
federatedIdentity.setToken(accessToken);
Expand All @@ -323,8 +347,6 @@ public Response LoginWithFederatedIdentity(@QueryParam(AbstractOAuth2IdentityPro
federatedIdentity.setIdpConfig(getConfig());
federatedIdentity.setIdp(WeiXinIdentityProvider.this);
federatedIdentity.setCode(state);

return callback.authenticated(federatedIdentity);
}

public SimpleHttp generateTokenRequest(String authorizationCode) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
public class WeixinIdentityCustomAuth extends AbstractOAuth2IdentityProvider<OAuth2IdentityProviderConfig>
implements SocialIdentityProvider<OAuth2IdentityProviderConfig> {

private WeiXinIdentityProvider weiXinIdentityProvider;
private final WeiXinIdentityProvider weiXinIdentityProvider;
public String accessToken;

public WeixinIdentityCustomAuth(KeycloakSession session, OAuth2IdentityProviderConfig config, WeiXinIdentityProvider weiXinIdentityProvider) {
Expand Down Expand Up @@ -45,9 +45,11 @@ public BrokeredIdentityContext auth(String openid) throws IOException {
var profile = SimpleHttp.doGet(String.format("https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid" +
"=%s&lang=zh_CN", accessToken, openid), this.session).asJson();


System.out.println("profile is " + profile);

return this.weiXinIdentityProvider.extractIdentityFromProfile(null, profile);
var context = this.weiXinIdentityProvider.extractIdentityFromProfile(null, profile);
context.getContextData().put(FEDERATED_ACCESS_TOKEN, accessToken);

return context;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,8 @@ public void setCustomizedLoginUrlForPc(String customizedLoginUrlForPc) {
public String getCustomizedLoginUrlForPc() {
return this.getConfig().get(CUSTOMIZED_LOGIN_URL_FOR_PC);
}

public void setClientId2(String clientId2) {
this.getConfig().put("clientId2", clientId2);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

import javax.ws.rs.core.Response;

import static org.keycloak.social.weixin.WeiXinIdentityProvider.WECHAT_APPID_KEY;

@RunWith(PowerMockRunner.class)
@PrepareForTest({UUID.class, WeiXinIdentityProvider.class})
public class WeixinIdentityProviderTest {
Expand Down Expand Up @@ -85,6 +87,7 @@ public void pcGoesToQRConnect() {
public void pcGoesToCustomizedURLIfPresent() {
var config = new WeixinProviderConfig();
config.setClientId("clientId");
config.setClientId2(WECHAT_APPID_KEY);
config.setCustomizedLoginUrlForPc("https://another.url/path");

Assert.assertEquals("set config get config", "https://another.url/path", config.getCustomizedLoginUrlForPc());
Expand All @@ -95,12 +98,14 @@ public void pcGoesToCustomizedURLIfPresent() {
var authSession = new MockedAuthenticationSessionModel();

HttpRequest httpRequest = new MockedHttpRequest();
AuthenticationRequest request = new AuthenticationRequest(null, null, authSession, httpRequest, null, state, "https" +
AuthenticationRequest request = new AuthenticationRequest(null, null, authSession, httpRequest, null, state,
"https" +
"://redirect.to.customized/url");

var res = weiXinIdentityProvider.performLogin(request);

Assert.assertEquals("303 redirect", Response.Status.SEE_OTHER.getStatusCode(), res.getStatus());
Assert.assertEquals("pc goes to customized login url", "https://another.url/path", res.getLocation().toString());
Assert.assertEquals("pc goes to customized login url", true,
res.getLocation().toString().startsWith("https://another.url/path"));
}
}
31 changes: 31 additions & 0 deletions src/test/java/org/keycloak/social/weixin/UtilTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.keycloak.social.weixin;

import org.junit.Assert;
import org.junit.Test;
import org.keycloak.broker.provider.BrokeredIdentityContext;

public class UtilTest {
@Test
public void inspectBrokeredIdentityContext() {
BrokeredIdentityContext context = new BrokeredIdentityContext("1234");

String inspected = Util.inspect("context", context);

Assert.assertEquals("context >>>\n" +
"\tid: 1234\n" +
"\tusername: null\n" +
"\tmodelUsername: null\n" +
"\temail: null\n" +
"\tfirstName: null\n" +
"\tlastName: null\n" +
"\tbrokerSessionId: null\n" +
"\tbrokerUserId: null\n" +
"\tcode: null\n" +
"\ttoken: null\n" +
"\tidpConfig: null\n" +
"\tidp: null\n" +
"\tcontextData: {}\n" +
"\tauthenticationSession: null\n" +
"context <<<\n", inspected);
}
}

0 comments on commit b409e3d

Please sign in to comment.