Skip to content

Commit 8a36e04

Browse files
Fix Weixin NameIdentifier claim value (#671)
* Fix the value declared by the weixin provider NameIdentifier claim * add test case for weixin provider * Add a test case with an empty unionid in the WechatTests class
1 parent c947162 commit 8a36e04

File tree

5 files changed

+60
-1
lines changed

5 files changed

+60
-1
lines changed

src/AspNet.Security.OAuth.Weixin/WeixinAuthenticationConstants.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@ public static class Claims
1818
public const string OpenId = "urn:weixin:openid";
1919
public const string Privilege = "urn:weixin:privilege";
2020
public const string Province = "urn:weixin:province";
21+
public const string UnionId = "urn:weixin:unionid";
2122
}
2223
}

src/AspNet.Security.OAuth.Weixin/WeixinAuthenticationHandler.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ protected override async Task<AuthenticationTicket> CreateTicketAsync(
7979
throw new HttpRequestException("An error occurred while retrieving user information.");
8080
}
8181

82+
(var openId, var unionId) = GetUserIdentifier(payload.RootElement);
83+
var nameIdentifier = !string.IsNullOrWhiteSpace(unionId) ? unionId : openId;
84+
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, nameIdentifier!, ClaimValueTypes.String, Options.ClaimsIssuer));
85+
8286
var principal = new ClaimsPrincipal(identity);
8387
var context = new OAuthCreatingTicketContext(principal, properties, Context, Scheme, Options, Backchannel, tokens, payload.RootElement);
8488
context.RunClaimActions();
@@ -176,6 +180,11 @@ protected override string BuildChallengeUrl([NotNull] AuthenticationProperties p
176180
return challengeUrl;
177181
}
178182

183+
private static (string? OpenId, string? UnionId) GetUserIdentifier(JsonElement payloadRoot)
184+
{
185+
return (payloadRoot.GetString("openid"), payloadRoot.GetString("unionid"));
186+
}
187+
179188
/// <inheritdoc/>
180189
protected override string FormatScope()
181190
=> FormatScope(Options.Scope); // TODO This override is the same as the base class' and can be removed in the next major version

src/AspNet.Security.OAuth.Weixin/WeixinAuthenticationOptions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ public WeixinAuthenticationOptions()
2626
Scope.Add("snsapi_login");
2727
Scope.Add("snsapi_userinfo");
2828

29-
ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "unionid");
3029
ClaimActions.MapJsonKey(ClaimTypes.Name, "nickname");
3130
ClaimActions.MapJsonKey(ClaimTypes.Gender, "sex");
3231
ClaimActions.MapJsonKey(ClaimTypes.Country, "country");
3332
ClaimActions.MapJsonKey(Claims.OpenId, "openid");
33+
ClaimActions.MapJsonKey(Claims.UnionId, "unionid");
3434
ClaimActions.MapJsonKey(Claims.Province, "province");
3535
ClaimActions.MapJsonKey(Claims.City, "city");
3636
ClaimActions.MapJsonKey(Claims.HeadImgUrl, "headimgurl");

test/AspNet.Security.OAuth.Providers.Tests/Wechat/WechatTests.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,34 @@ public async Task Can_Sign_In_Using_Wechat(string claimType, string claimValue)
4545
// Assert
4646
AssertClaim(claims, claimType, claimValue);
4747
}
48+
49+
[Theory]
50+
[InlineData(ClaimTypes.NameIdentifier, "my-open-id")]
51+
[InlineData(ClaimTypes.Name, "John Smith")]
52+
[InlineData(ClaimTypes.Gender, "Male")]
53+
[InlineData(ClaimTypes.Country, "CN")]
54+
[InlineData("urn:weixin:city", "Beijing")]
55+
[InlineData("urn:weixin:headimgurl", "https://weixin.qq.local/image.png")]
56+
[InlineData("urn:weixin:openid", "my-open-id")]
57+
[InlineData("urn:weixin:privilege", "a,b,c")]
58+
[InlineData("urn:weixin:province", "Hebei")]
59+
public async Task Can_Sign_In_Using_Weixin_With_No_Unionid(string claimType, string claimValue)
60+
{
61+
// Arrange
62+
static void ConfigureServices(IServiceCollection services)
63+
{
64+
services.PostConfigureAll<WeixinAuthenticationOptions>((options) =>
65+
{
66+
options.UserInformationEndpoint = "https://api.weixin.qq.com/sns/userinfo/nounionid";
67+
});
68+
}
69+
70+
using var server = CreateTestServer(ConfigureServices);
71+
72+
// Act
73+
var claims = await AuthenticateUserAsync(server);
74+
75+
// Assert
76+
AssertClaim(claims, claimType, claimValue);
77+
}
4878
}

test/AspNet.Security.OAuth.Providers.Tests/Wechat/bundle.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,25 @@
3030
"c"
3131
]
3232
}
33+
},
34+
{
35+
"uri": "https://api.weixin.qq.com/sns/userinfo/nounionid?access_token=secret-access-token&openid=my-open-id",
36+
"contentFormat": "json",
37+
"contentJson": {
38+
"unionid": "",
39+
"nickname": "John Smith",
40+
"sex": "Male",
41+
"country": "CN",
42+
"openid": "my-open-id",
43+
"province": "Hebei",
44+
"city": "Beijing",
45+
"headimgurl": "https://weixin.qq.local/image.png",
46+
"privilege": [
47+
"a",
48+
"b",
49+
"c"
50+
]
51+
}
3352
}
3453
]
3554
}

0 commit comments

Comments
 (0)