c# - 如何在移动应用程序上进行身份验证后在 .NET Core 服务器上登录用户

标签 c# asp.net-core google-api google-authentication

我在 .NET Core Web API 应用身份验证方面遇到了问题。 我想要: 1) 在移动应用程序(目前为 iOS)上使用 Google 对用户进行身份验证 2) 使用此身份验证,使用 AspNetCore.Identity 和 Entity Framework Core 在数据库中创建用户记录 3) 使用相同的身份验证,从 .NET Core 服务器调用 Google Calendar API

到目前为止,我已经弄清楚如何实现 1 和 3,但无法理解第 2 点。

我的理解是,由于文档原因,要登录第三方认证的用户,您需要使用 SignInManager 实例方法 ExternalLoginSignInAsync .它需要两个参数: login provider(应该是简单的“Google”)和唯一的provider key。我的问题是我找不到任何可以买到的地方。

以下是我在移动应用程序上从 Google 登录结果中收到的所有内容的列表: enter image description here

这是我尝试调用的方法。

// POST api/signup
    [HttpPost]
    public async Task<bool> Post([FromBody]string authorizationCode, [FromBody]string userId)
    {
        var tokenFromAuthorizationCode = await GetGoogleTokens(userId, authorizationCode);
        var result = await signInManager.ExternalLoginSignInAsync(
            "Google", tokenFromAuthorizationCode.IdToken, false);
        if (result.Succeeded)
            return true;

        var externalLoginInfo = new ExternalLoginInfo(
            ClaimsPrincipal.Current, "Google", tokenFromAuthorizationCode.IdToken, null);
        return await SignInUser(externalLoginInfo);
    }

    private async Task<bool> SignInUser(ExternalLoginInfo info)
    {
        var newUser = new AppUser { Email = "test@test.com", UserName = "TestUser" };
        var identResult = await userManager.CreateAsync(newUser);
        if (identResult.Succeeded)
        {
            identResult = await userManager.AddLoginAsync(newUser, info);
            if (identResult.Succeeded)
            {
                await signInManager.SignInAsync(newUser, false);
                return true;
            }
        }

        return false;
    }

    private async Task<TokenResponse> GetGoogleTokens(string userId, string authorizationCode)
    {
        TokenResponse token;
        try
        {
            // TODO: Save access and refresh token to AppUser object
            token = await authFlow.Flow.ExchangeCodeForTokenAsync(
                userId, authorizationCode, "http://localhost:60473/signin-google", CancellationToken.None);
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
            throw;
        }

        return token;
    }

我的问题是:如果您通过 REST API 构建身份验证,这是正确的路径吗?如果是,我从哪里可以获得 Google 的提供商 key ? 提前致谢。

最佳答案

显然,provider key 只是来自 Google 的user id。 这是对我有用的解决方案:

       [HttpPost]
    public async Task<AppUser> Post([FromBody]GoogleSignInCredentials credentials)
    {
        // 1. get user id from idToken
        var oauthService = new Oauth2Service(new BaseClientService.Initializer { ApiKey = "{your api key}" });
        var tokenInfoRequest = oauthService.Tokeninfo();
        tokenInfoRequest.IdToken = credentials.IdToken;
        var userInfo = await tokenInfoRequest.ExecuteAsync();

        // 2. get access_token and refresh_token with new id and authorization code
        var tokenFromAuthorizationCode = await GetGoogleTokens(userInfo.UserId, credentials.AuthorizationCode);

        // 3. check if user exists
        var result = await _signInManager.ExternalLoginSignInAsync(
            "Google", userInfo.UserId, false);
        if (result.Succeeded)
            return await _userManager.FindByEmailAsync(userInfo.Email); 

        // 4. create user account
        var externalLoginInfo = new ExternalLoginInfo(
            ClaimsPrincipal.Current, "Google", userInfo.UserId, null);

        // 5. fetch user
        var createdUser = await SignInUser(externalLoginInfo, userInfo.Email);
        if (createdUser != null)
        {
            createdUser.GoogleAccessToken = tokenFromAuthorizationCode.AccessToken;
            createdUser.GoogleRefreshToken = tokenFromAuthorizationCode.RefreshToken;
            var updateResult = await _userManager.UpdateAsync(createdUser);
            if (updateResult.Succeeded)
                return createdUser;

            return null;
        }

        return null;
    }

    private async Task<AppUser> SignInUser(ExternalLoginInfo info, string email)
    {
        var newUser = new AppUser { Email = email, UserName = email };
        var identResult = await _userManager.CreateAsync(newUser);
        if (identResult.Succeeded)
        {
            identResult = await _userManager.AddLoginAsync(newUser, info);
            if (identResult.Succeeded)
            {
                await _signInManager.SignInAsync(newUser, false);
                return await _userManager.FindByEmailAsync(email);
            }
        }

        return null;
    }

    private async Task<TokenResponse> GetGoogleTokens(string userId, string authorizationCode)
    {
        return await _authFlow.Flow.ExchangeCodeForTokenAsync(
                userId, authorizationCode, "http://localhost:60473/signin-google", CancellationToken.None);
    }

关于c# - 如何在移动应用程序上进行身份验证后在 .NET Core 服务器上登录用户,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44220193/

相关文章:

c# - Visual Studio docker 工具在调试时发布端口

jquery - 当我在 ASP.NET Core 中发送多个属性时,如何使用 Ajax 将数据发布到 Controller 模型?

c# - asp.net 和 javascript 中的正则表达式语法是否相同?

c# - 制作可换肤的用户界面组件的次优方法是什么?

c# - 如何让 XamlReader.Parse 不抛出 "property does not exist"XamlParseException?

curl - 使用cURL Google API从刷新 token 获取访问 token

javascript - 未捕获的 InvalidValueError : initAutocomplete is not a function

c# - 如何覆盖基本 Controller 中 Json 辅助方法的行为

c# - 在 asp.net vnext 中获取应用程序路径

google-api - 服务帐户 (403) Forbidden Google Play In-app Billing Purchase Status API