针对.net后端服务器验证Google ID

时间:2015-11-28 16:38:38

标签: .net google-signin

我正在尝试为我的应用实施Google登录。

后端服务器将是c#.net ....

有些人可以指出我的方向,或解释如何在.Net中进行后端验证......他们提供了java示例并建议使用googles apis

answer to the similar question

1 个答案:

答案 0 :(得分:3)

有同样的问题。 您在服务器端需要的是验证您在客户端获得的“id令牌”。 因此,首先在客户端通过以下方式获取“id token”:

function onGoogleSignIn(googleUser)
{
    //Here call ajax and pass googleUser.getAuthResponse().id_token
}

好的,现在在服务器端,您可以使用以下函数来验证令牌:

public sealed class JWTCertificateUrl
{
    private JWTCertificateUrl(string value) { Value = value; }
    public string Value { get; set; }

    public static JWTCertificateUrl Google { get { return new JWTCertificateUrl("https://www.googleapis.com/oauth2/v1/certs"); } }
}

public sealed class JWTIssuer
{
    private JWTIssuer(string value) { Value = value; }
    public string Value { get; set; }

    public static JWTIssuer None { get { return new JWTIssuer(""); } }
    public static JWTIssuer Google { get { return new JWTIssuer("accounts.google.com"); } }
}

public static class Utils
{
    private const string beginCert = "-----BEGIN CERTIFICATE-----\\n";
    private const string endCert = "\\n-----END CERTIFICATE-----\\n";
    private static byte[][] getCertBytes(JWTCertificateUrl certificate)
    {
        // The request will be made to the authentication server.
        WebRequest request = WebRequest.Create(certificate.Value);

        StreamReader reader = new StreamReader(request.GetResponse().GetResponseStream());

        string responseFromServer = reader.ReadToEnd();

        String[] split = responseFromServer.Split(':');

        // There are two certificates returned from Google
        byte[][] certBytes = new byte[2][];
        int index = 0;
        UTF8Encoding utf8 = new UTF8Encoding();
        for (int i = 0; i < split.Length; i++)
        {
            if (split[i].IndexOf(beginCert) > 0)
            {
                int startSub = split[i].IndexOf(beginCert);
                int endSub = split[i].IndexOf(endCert) + endCert.Length;
                certBytes[index] = utf8.GetBytes(split[i].Substring(startSub, endSub).Replace("\\n", "\n"));
                index++;
            }
        }
        return certBytes;
    }

    public static bool CheckJWTToken(JWTCertificateUrl cert, JWTIssuer tokenIssuer, string appId, string idToken, ref Dictionary<string, string> data)
    {
        if (data == null)
            data = new Dictionary<string, string>();

        if (string.IsNullOrEmpty(idToken))
            return false;

        //JwtSecurityToken token = new JwtSecurityToken(idToken);
        JwtSecurityTokenHandler jsth = new JwtSecurityTokenHandler();

        Byte[][] certBytes = getCertBytes(cert);
        Dictionary<String, X509Certificate2> certificates = new Dictionary<String, X509Certificate2>();
        for (int i = 0; i < certBytes.Length; i++)
        {
            X509Certificate2 certificate = new X509Certificate2(certBytes[i]);
            certificates.Add(certificate.Thumbprint, certificate);
        }

        TokenValidationParameters tvp = new TokenValidationParameters()
        {
            ValidateActor = false, // check the profile ID

            ValidateAudience = true,
            ValidAudience = appId,

            ValidateIssuer = !string.IsNullOrEmpty(tokenIssuer.Value),
            ValidIssuer = tokenIssuer.Value,

            ValidateIssuerSigningKey = true,
            RequireSignedTokens = true,
            CertificateValidator = X509CertificateValidator.None,
            IssuerSigningKeyResolver = (s, securityToken, identifier, parameters) =>
            {
                return identifier.Select(x =>
                {
                    if (certificates.ContainsKey(x.Id.ToUpper()))
                    {
                        return new X509SecurityKey(certificates[x.Id.ToUpper()]);
                    }
                    return null;
                }).First(x => x != null);
            },
            ValidateLifetime = true,
            RequireExpirationTime = true,
            ClockSkew = TimeSpan.FromSeconds(300) //5 minutes
        };

        bool res = false;
        try
        {
            // Validate using the provider
            SecurityToken validatedToken;
            ClaimsPrincipal cp = jsth.ValidateToken(idToken, tvp, out validatedToken);
            if (cp != null)
            {
                foreach (var claim in cp.Claims)
                {
                    var name = claim.Type;
                    //Delete the URL part just for convenient
                    if (name.StartsWith("http"))
                        name = name.Remove(0, name.LastIndexOf('/') + 1);
                    data.Add(name, claim.Value);
                }
                res = true;
            }

        }
        catch (Exception ex)
        {
        }

        return res;
    }
}

函数调用:

Dictionary<string, string> data = null;
if (Utils.CheckJWTToken(JWTCertificateUrl.Google, JWTIssuer.Google, "[your google app id].apps.googleusercontent.com", idToken, ref data))
{
  //Here you can take user data for further process
  //data["emailaddress"], data["givenname"], data["surname"]
}

为了编译代码,您需要从此处安装.NET JWT库:https://www.nuget.org/packages/System.IdentityModel.Tokens.Jwt/

上面的代码来自https://github.com/googleplus/gplus-verifytoken-csharp