How to sign in user on .NET Core server after authentication on Mobile App

有些话、适合烂在心里 提交于 2019-12-08 02:11:55

问题


I'm having troubles .NET Core Web API app authentication. I want to: 1) Authenticate user with Google on Mobile App (currently iOS) 2) Using this authentication, create user record in database using AspNetCore.Identity and Entity Framework Core 3) Using same authentication, call Google Calendar API from .NET Core server

So far I figured out how to implement 1 and 3, but can't wrap my head around number 2.

My understanding is that to sign in user authenticated with third-party, due to documentation, you need to use SignInManager instance method ExternalLoginSignInAsync. It takes two arguments: login provider (should be simple stirng as "Google") and unique provider key. My problem is that I can't find anywhere where can I get one.

Here is the list of all things I receive from Google Sign In result on mobile app:

Here is the method I try to call in.

// 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;
    }

My question is: is it a correct path if you're building authentication via REST API, and if so, where could I get Google's provider key? Thanks in advance.


回答1:


Well apparently, provider key is just user id from Google. Here is the solution that worked for me:

       [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);
    }


来源:https://stackoverflow.com/questions/44220193/how-to-sign-in-user-on-net-core-server-after-authentication-on-mobile-app

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!