Получить электронную почту пользователя из Mastodon API через OAuth
Можно ли получить электронную почту пользователя через Mastodon Api? Я работаю над добавлением аутентификации OAuth через Mastodon Api, но, похоже, получаю только"id"
и"display_name"
с использованием"/api/v1/accounts/verify_credentials"
конечная точка. Я не вижу свойство, возвращенное для электронной почты, поэтому в настоящее время просто использую"acct"
параметр. я использую оба"read:accounts"
и"admin:read:accounts"
масштабы. Это для приложения NetCore.
builder.Services.AddAuthentication()
.AddMicrosoftAccount("Microsoft", "Microsoft", microsoftOptions =>
{
microsoftOptions.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
microsoftOptions.ClientId = _appSettings.Authentication.Microsoft.ClientId;
microsoftOptions.ClientSecret = _appSettings.Authentication.Microsoft.ClientSecret;
})
.AddGoogle("Google", "Google", googleOptions =>
{
googleOptions.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
googleOptions.ClientId = _appSettings.Authentication.Google.ClientId;
googleOptions.ClientSecret = _appSettings.Authentication.Google.ClientSecret;
})
.AddGitHub("GitHub", "GitHub", githubOptions =>
{
githubOptions.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
githubOptions.ClientId = _appSettings.Authentication.GitHub.ClientId;
githubOptions.ClientSecret = _appSettings.Authentication.GitHub.ClientSecret;
})
.AddOAuth("Fosstodon", "Fosstodon", fosstodonOptions =>
{
fosstodonOptions.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
fosstodonOptions.ClientId = _appSettings.Authentication.Fosstodon.ClientId;
fosstodonOptions.ClientSecret = _appSettings.Authentication.Fosstodon.ClientSecret;
fosstodonOptions.CallbackPath = new PathString("/signin-fosstodon");
fosstodonOptions.AuthorizationEndpoint = _appSettings.Authentication.Fosstodon.AuthorizationEndpoint;
fosstodonOptions.TokenEndpoint = _appSettings.Authentication.Fosstodon.TokenEndpoint;
fosstodonOptions.UserInformationEndpoint = _appSettings.Authentication.Fosstodon.UserInformationEndpoint;
fosstodonOptions.SaveTokens = true;
fosstodonOptions.Scope.Add("read:accounts");
fosstodonOptions.Scope.Add("admin:read:accounts");
fosstodonOptions.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "id");
fosstodonOptions.ClaimActions.MapJsonKey(ClaimTypes.Name, "name");
fosstodonOptions.ClaimActions.MapJsonKey(ClaimTypes.Email, "email");
fosstodonOptions.Events = new OAuthEvents
{
OnCreatingTicket = async context =>
{
var request = new HttpRequestMessage(HttpMethod.Get, context.Options.UserInformationEndpoint);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken);
var response = await context.Backchannel.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, context.HttpContext.RequestAborted);
response.EnsureSuccessStatusCode();
var user = JObject.Parse(await response.Content.ReadAsStringAsync());
var identifier = user.Value<string>("id")?.Clean();
if (!string.IsNullOrEmpty(identifier))
{
context.Identity?.AddClaim(new Claim(
ClaimTypes.NameIdentifier, identifier,
ClaimValueTypes.String, context.Options.ClaimsIssuer));
}
var userName = user.Value<string>("display_name")?.Clean();
if (!string.IsNullOrEmpty(userName))
{
context.Identity?.AddClaim(new Claim(
ClaimTypes.Name, userName,
ClaimValueTypes.String, context.Options.ClaimsIssuer));
}
var userEmail = user.Value<string>("acct")?.Clean();
if (!string.IsNullOrEmpty(userEmail))
{
context.Identity?.AddClaim(new Claim(
ClaimTypes.Email, userEmail,
ClaimValueTypes.String, context.Options.ClaimsIssuer));
}
}
};
});
Действительно хочу знать, является ли их конечная точка, которая вернет текущий адрес электронной почты пользователя. Я просмотрел документацию Mastodon Api , но не увидел и не указал на это.
1 ответ
Обнаружено, что невозможно получить электронную почту пользователя через Mastodon Api. Вместо этого решил обработать эту ситуацию в процессе регистрации потока аутентификации приложения. В основном проверьте, существует ли пользователь с данным адресом электронной почты. Если это так, удалите пользователя с автоматической подготовкой и добавьте информацию о внешнем поставщике существующему пользователю. Позже будет отправлено подтверждение электронной почты на указанный адрес электронной почты, чтобы кто-то не мог украсть учетную запись пользователя при регистрации.
/// <summary>
/// Handle postback from new registration
/// </summary>
/// <returns>IActionResult</returns>
[AllowAnonymous]
[HttpPost("Registration/New")]
[HttpPost("Registration/New/{id?}")]
[ValidateAntiForgeryToken]
public virtual async Task<IActionResult> New([Bind(RegistrationViewModel.BindProperties)] RegistrationViewModel model, [FromForm(Name = "Button")] string button)
{
// Check if cancled
if (button.Clean() != "submit")
return RedirectToAction("Index", "Home");
// Check email is valid
if (!model.Email.Clean().IsValidEmail())
ModelState.AddModelError(nameof(model.Email), _sharedLocalizer["ErrorMessage.Invalid"]);
if (ModelState.IsValid)
{
// setup results
IdentityResult identityResult = new IdentityResult();
// Check for existing user
ApplicationUser user = await _userManager.FindByEmailAsync(model.Email.Clean());
if (user != null)
{
if (user.Id != model.Id.Clean())
{
ApplicationUser removeUser = await _userManager.FindByIdAsync(model.Id.Clean());
if (removeUser != null)
{
identityResult = await _userManager.DeleteAsync(removeUser);
if (!identityResult.Succeeded) throw new Exception(identityResult.Errors.First().Description);
}
}
}
else
{
user = await _userManager.FindByIdAsync(model.Id.Clean());
if (user == null)
throw new KeyNotFoundException($"[Key]: {nameof(model.Id)} [Value]: {model.Id}");
}
user.DisplayName = model.DisplayName.Clean();
user.UserName = model.Email.Clean();
user.NormalizedUserName = model.Email.Clean();
user.Email = model.Email.Clean();
user.NormalizedEmail = model.Email.Clean();
identityResult = await _userManager.UpdateAsync(user);
if (!identityResult.Succeeded) throw new Exception(identityResult.Errors.First().Description);
if (!string.IsNullOrEmpty(model.ProviderUserId.Clean()))
{
var userLogins = await _userManager.GetLoginsAsync(user);
UserLoginInfo? userLogin = userLogins
.Where(x => x.LoginProvider == model.Provider.Clean())
.Where(x => x.ProviderKey == model.ProviderUserId.Clean())
.FirstOrDefault();
if (userLogin == null)
{
identityResult = await _userManager.AddLoginAsync(user, new UserLoginInfo(model.Provider.Clean(), model.ProviderUserId.Clean(), model.Provider.Clean()));
if (!identityResult.Succeeded) throw new Exception(identityResult.Errors.First().Description);
}
}
}
return View(model);
}