问题
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