По сути, я следовал этому ответу SO для материалов, не связанных с firebase, и это руководство для материалов Firebase и все это работает, у меня есть доступ к пользователю, токену доступа, утверждениям, ко всему, через extendedContext.userResolverService, и токен идентификатора проверяется во всех конечных точках моего веб-контроллера, которые используют [Authorize]
.
Поскольку у меня есть токен id во всех моих контроллерах, я мог бы вручную вызвать его с любого контроллера, однако в этом нет необходимости.
FirebaseToken decodedToken = await FirebaseAuth.DefaultInstance
.VerifyIdTokenAsync(idToken);
string uid = decodedToken.Uid;
userResolverService.cs:
using System.Security.Claims;
using Microsoft.AspNetCore.Http;
public class UserResolverService
{
public readonly IHttpContextAccessor _context;
public UserResolverService(IHttpContextAccessor context)
{
_context = context;
}
public string GetGivenName()
{
return _context.HttpContext.User.FindFirst(ClaimTypes.GivenName).Value;
}
public string GetSurname()
{
return _context.HttpContext.User.FindFirst(ClaimTypes.Surname).Value;
}
public string GetNameIdentifier()
{
return _context.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;
}
public string GetEmails()
{
return _context.HttpContext.User.FindFirst("emails").Value;
}
}
Расширьте DataContext (через композицию):
namespace Vepo.DataContext {
public class ExtendedVepoContext
{
public VepoContext _context;
public UserResolverService _userResolverService;
public ExtendedVepoContext(VepoContext context, UserResolverService userService)
{
_context = context;
_userResolverService = userService;
_context._currentUserExternalId = _userResolverService.GetNameIdentifier();
}
}
}
запуск.cs:
public void ConfigureServices(IServiceCollection services)
{
....
services.AddHttpContextAccessor();
services.AddTransient<UserResolverService>();
services.AddTransient<ExtendedVepoContext>();
FirebaseApp.Create(new AppOptions()
{
Credential = GoogleCredential.FromFile("firebase_admin_sdk.json"),
});
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = "https://securetoken.google.com/my-firebase-app-id";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = "https://securetoken.google.com/my-firebase-app-id",
ValidateAudience = true,
ValidAudience = "my-firebase-app-id",
ValidateLifetime = true
};
});
также startup.cs:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, VepoContext context, ISearchIndexService searchIndexService)
{ ....
app.UseAuthentication();
app.UseAuthorization();
Затем добавьте авторизацию в конечную точку контроллера следующим образом:
[HttpPost]
[Authorize]
public async Task<ActionResult<GroceryItemGroceryStore>> PostGroceryItemGroceryStore(GroceryItemGroceryStore groceryItemGroceryStore)
{...
Вы можете сделать еще один шаг и делать что-то с пользователем при каждом сохранении и т. д., например добавлять метаданные:
объект для сохранения с добавленными метаданными:
public interface IDomainEntity<TId>
{
TId Id { get; set; }
DateTime SysStartTime { get; set; }
DateTime SysEndTime { get; set; }
string CreatedById { get; set; }
User CreatedBy { get; set; }
string UpdatedById { get; set; }
User UpdatedBy { get; set; }
}
мой контекст данных:
public class VepoContext : DbContext
{
public VepoContext(DbContextOptions<VepoContext> options)
: base(options)
{
}
public DbSet<User> User { get; set; }
public string _currentUserExternalId;
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken))
{
var user = await User.SingleAsync(x => x.Id == _currentUserExternalId);
AddCreatedByOrUpdatedBy(user);
return (await base.SaveChangesAsync(true, cancellationToken));
}
public override int SaveChanges()
{
var user = User.Single(x => x.Id == _currentUserExternalId);
AddCreatedByOrUpdatedBy(user);
return base.SaveChanges();
}
public void AddCreatedByOrUpdatedBy(User user)
{
foreach (var changedEntity in ChangeTracker.Entries())
{
if (changedEntity.Entity is IDomainEntity<int> entity)
{
switch (changedEntity.State)
{
case EntityState.Added:
entity.CreatedBy = user;
entity.UpdatedBy = user;
break;
case EntityState.Modified:
Entry(entity).Reference(x => x.CreatedBy).IsModified = false;
entity.UpdatedBy = user;
break;
}
}
}
}
person
BeniaminoBaggins
schedule
26.06.2021