I may get claims using DI in asp.core1, as in the below
public class UserService : IUserService
{
private IHttpContextAccessor _httpContext;
public UserService(IHttpContextAccessor httpContext)
{
_httpContext = httpContext;
}
}
In case with In asp.core 2, _httpContext.User.Identity.IsAuthenticated has the value false, and doesn't contain claims.
My startup.cs looks like this:
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddAuthentication(o =>
{
o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters
{
// ...
};
});
services.AddCors();
services.AddMvc();
services.AddTransient<IUserService, UserService>();
services.AddTransient<IHttpContextAccessor, HttpContextAccessor();
}
Related
I am trying to setup a custom authorization handler in my project closely following the Resource-based authorization in ASP.NET Core Microsoft documentation. However, calling the API endpoint always returns a 403 response and doesn't even trigger a breakpoint in my handler.
Feels like I quadruple checked every single thing yet it still doesn't work. Am I blind or is there something wrong with my code?
Here's my custom handler:
public class TripAuthorizationHandler : AuthorizationHandler<SameUserRequirement, Trip>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, SameUserRequirement requirement, Trip resource)
{
if(context.User.FindFirst("userId").Value == resource.ApplicationUserId)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
public class SameUserRequirement : IAuthorizationRequirement{}
Program.cs file:
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["JWT:Issuer"],
ValidAudience = builder.Configuration["JWT:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["JWT:Key"]))
};
});
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("SameUser", policy => policy.Requirements.Add(new SameUserRequirement()));
});
builder.Services.AddTransient<IAuthorizationHandler, TripAuthorizationHandler>();
builder.Services.AddTransient<IAuthenticationService, AuthenticationService>();
builder.Services.AddTransient<ITokenService, TokenService>();
builder.Services.AddAutoMapper(typeof(Program));
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseMiddleware<ExceptionHandlingMiddleware>();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
And here's the controller:
[Authorize(Policy = "SameUser")]
[HttpPut("trips/{tripId}")]
public async Task<IActionResult> UpdateTrip([FromBody] TripPostDto request, int tripId)
{
var trip = await _tripService.GetByIdAsync(tripId);
var authorizationResult = await _authorizationService.AuthorizeAsync(User, trip, "SameUser");
if (authorizationResult.Succeeded)
{
await _tripService.UpdateAsync(tripId, request);
return NoContent();
}
else if (User.Identity.IsAuthenticated)
{
return Forbid();
}
else
{
return Challenge();
}
}
Edit:
Here's my implementation of AuthenticationService
public class AuthenticationService : IAuthenticationService
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly ITokenService _tokenService;
private readonly IMapper _mapper;
public AuthenticationService(UserManager<ApplicationUser> userManager, IMapper mapper, ITokenService tokenService)
{
_userManager = userManager;
_mapper = mapper;
_tokenService = tokenService;
}
public async Task<SuccessfulLoginDto> LoginAsync(LoginUserDto loginUserDto)
{
var user = await _userManager.FindByEmailAsync(loginUserDto.Email);
if(user == null)
{
throw new ValidationException("Invalid login data!");
}
var passwordValid = await _userManager.CheckPasswordAsync(user, loginUserDto.Password);
if (!passwordValid)
{
throw new ValidationException("Invalid login data!");
}
var accessToken = await _tokenService.GetTokenAsync(user);
return new SuccessfulLoginDto() { Token = accessToken.AccessToken };
}
public async Task RegisterAsync(RegisterUserDto registerUserDto)
{
var existingUser = await _userManager.FindByEmailAsync(registerUserDto.Email);
if (existingUser != null)
{
throw new UserAlreadyExistsException("User with this email already exists!");
}
var newUser = _mapper.Map<ApplicationUser>(registerUserDto);
var result = await _userManager.CreateAsync(newUser, registerUserDto.Password);
if (!result.Succeeded)
{
throw new ValidationException(string.Join(" ", result.Errors.Select(e => e.Description)));
}
await _userManager.AddToRoleAsync(newUser, Authorization.Roles.User.ToString());
}
}
Have you tried ordering the service injection before?
Order matters in Startup
builder.Services.AddTransient<IAuthorizationHandler, TripAuthorizationHandler>();
builder.Services.AddTransient<IAuthenticationService, AuthenticationService>();
builder.Services.AddTransient<ITokenService, TokenService>();
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["JWT:Issuer"],
ValidAudience = builder.Configuration["JWT:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["JWT:Key"]))
};
});
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("SameUser", policy => policy.Requirements.Add(new SameUserRequirement()));
});
Authorize signalR Hub not getting connect to hub with front end angular, unable to invoke jwt access token to hub connection. How to connect Authurized signalr hub in asp core with angular project
i have the following code in my project,
Here my Code
public class Startup
{
readonly string CorsPolicy = "CorsPolicy";
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddCors(options =>
{
options.AddPolicy(name: CorsPolicy,
builder =>
{
builder
.AllowAnyHeader()
.AllowAnyMethod()
.WithOrigins("http://localhost:3000", "http://localhost:4200", "http://localhost:1234")
.AllowCredentials();
});
});
services.AddControllers();
services.AddSignalR()
.AddJsonProtocol(options =>
{
options.PayloadSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
});
//jwt token
services.AddAuthentication(opt =>
{
opt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
opt.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
opt.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.RequireHttpsMetadata = false;
options.SaveToken = false;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = Configuration["Jwt:Issuer"],
ValidAudience = Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"])),
ClockSkew = TimeSpan.Zero
};
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var accessToken = "Bearer " + context.Request.Query["access_token"];
var path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(accessToken) &&
(path.StartsWithSegments("/connecthub")))
{
// Read the token out of the query string
context.Token = accessToken;
}
return Task.CompletedTask;
}
};
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ApplicationDatabaseContext context)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseCors(CorsPolicy);
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHub<signalR_Hub>("/connecthub");
});
}
}
}
This my Hub connection
[Authorize]
public class sample_Hub :Hub
{
}
This my controller
[Authorize]
[HttpPut("{id}")]
public async Task<IActionResult> Putfilecreations(string id, filecreations filecreations)
{
var entity = _context.file_creations.Where(x => x.file_creation_id == id).FirstOrDefault();
entity.client_type_id = filecreations.client_type_id;
_context.file_creations.Update(entity);
await _context.SaveChangesAsync();
await _hubContext.Clients.All.SendAsync("FileUpdated", entity);
return Ok(entity);
}
This my Angular code for connect Hub
this.hubConnection = new HubConnectionBuilder()
.withUrl(environment.baseUrls.server + 'connecthub')
.configureLogging(LogLevel.Information)
.build();
Try to add CORS this way, the order is important:
services.AddCors(options =>
{
options.AddPolicy(CorsPolicy, builder => builder.WithOrigins("http://localhost:3000", "http://localhost:4200", "http://localhost:1234"")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials()
.SetIsOriginAllowed((host) => true));
});
I'm working on the latest ASP.NET Core 3.0 Angular template. What I need to know is how we can get authenticated user, username in ActionFilterAttribute.
The ClaimTypes.NameIdentifier returns the current user id, and ClaimTypes.Name returns the username which is null.
Here is my code:
where getUser has a UserId of d15f997a-6f65-4eb2-aecb-8b525361ae50
I've also register IHttpContextAccessor in the Startup class as follows:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<ApplicationUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
services.AddAuthentication()
.AddIdentityServerJwt();
//Database Setup
services.AddDbContext<HashooDBContext>(Configuration.GetConnectionString("DefaultConnection"));
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddControllersWithViews();
services.AddRazorPages();
// In production, the Angular files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
return ContainerSetup.InitializeWeb(Assembly.GetExecutingAssembly(), services);
}
Controller.cs:
[Authorize]
[ApiController]
[Route("api/[controller]/{companycode}")]
public class DashboardTransactionsController : ControllerBase
{
[CustomAuthorizationFilter("companycode")]
public string Get()
{
return "Welcome";
}
}
Please let me know what am I doing wrong?
You can use IHttpContextAccessor
private readonly IHttpContextAccessor _httpContextAccessor;
public UserService(
IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
And to get user name you can use
_httpContextAccessor?.HttpContext?.User?.Identity?.Name;
Or
_httpContextAccessor.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);
Then register in your Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
}
For this issue, it is caused by that the IdentityServer4 did not add the JwtClaimTypes.Name to the access_token. If you check the access_token from web brower, you will find it miss "name": "Tom", node.
For a workaround, you could implement your own ITokenService like
public class CustomTokenService : DefaultTokenService
{
public CustomTokenService(IClaimsService claimsProvider
, IReferenceTokenStore referenceTokenStore
, ITokenCreationService creationService
, IHttpContextAccessor contextAccessor
, ISystemClock clock
, IKeyMaterialService keyMaterialService
, ILogger<DefaultTokenService> logger)
: base(claimsProvider, referenceTokenStore, creationService, contextAccessor, clock, keyMaterialService, logger)
{
}
public override async Task<Token> CreateAccessTokenAsync(TokenCreationRequest request)
{
Logger.LogTrace("Creating access token");
request.Validate();
var claims = new List<Claim>();
claims.AddRange(await ClaimsProvider.GetAccessTokenClaimsAsync(
request.Subject,
request.Resources,
request.ValidatedRequest));
if (request.ValidatedRequest.Client.IncludeJwtId)
{
claims.Add(new Claim(JwtClaimTypes.JwtId, CryptoRandom.CreateUniqueId(16)));
}
claims.Add(new Claim(JwtClaimTypes.Name, request.Subject.GetDisplayName()));
var issuer = Context.HttpContext.GetIdentityServerIssuerUri();
var token = new Token(OidcConstants.TokenTypes.AccessToken)
{
CreationTime = Clock.UtcNow.UtcDateTime,
Issuer = issuer,
Lifetime = request.ValidatedRequest.AccessTokenLifetime,
Claims = claims.Distinct(new ClaimComparer()).ToList(),
ClientId = request.ValidatedRequest.Client.ClientId,
AccessTokenType = request.ValidatedRequest.AccessTokenType
};
foreach (var api in request.Resources.ApiResources)
{
if (!string.IsNullOrWhiteSpace(api.Name))
{
token.Audiences.Add(api.Name);
}
}
return token;
}
}
And then register CustomTokenService before Identity Configuration
public void ConfigureServices(IServiceCollection services)
{
services.TryAddTransient<ITokenService, CustomTokenService>();
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<ApplicationUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
services.AddAuthentication()
.AddIdentityServerJwt();
}
For a simple way, you could try to override DefaultClaimsService.GetStandardSubjectClaims like
public class CustomClaimsService : DefaultClaimsService
{
public CustomClaimsService(IProfileService profile
, ILogger<DefaultClaimsService> logger) : base(profile, logger)
{
}
protected override IEnumerable<Claim> GetStandardSubjectClaims(ClaimsPrincipal subject)
{
var claims = base.GetStandardSubjectClaims(subject);
var newClaims = new List<Claim>(claims)
{
new Claim(JwtClaimTypes.Name, subject.Identity.Name)
};
return newClaims;
}
}
And register like
public void ConfigureServices(IServiceCollection services)
{
services.TryAddTransient<IClaimsService, CustomClaimsService>();
//services.TryAddTransient<ITokenService, CustomTokenService>();
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<ApplicationUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
services.AddAuthentication()
.AddIdentityServerJwt();
}
Try this code:
string userId = context.HttpContext.User.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier).Value;
Seriously what am i doing wrong here? How is it possible for this to not work if the other policy is the inverse of the other? only 3 letters on the name change and reverse boolean check....
the policy HasArranqueActivo is the one working. I used debugger to test and it triggers it.
Here are policies declared
services.AddAuthorization(options =>
{
options.AddPolicy("HasArranqueActivo", policy =>
policy.Requirements.Add(new HasArranqueActivoRequirement()
));
options.AddPolicy("HasArranqueInactivo", policy =>
policy.Requirements.Add(new HasArranqueInactivoRequirement()
));
});
As you can see both handlers are basically the same
public class HasArranqueActivoHandler : AuthorizationHandler<HasArranqueActivoRequirement>
{
private readonly NoPaperContext _context;
public HasArranqueActivoHandler(NoPaperContext context)
{
_context = context;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, HasArranqueActivoRequirement requirement)
{
// Do something with _context
// Check if the requirement is fulfilled.
var registoId = Convert.ToInt32(context.User.FindFirst(c => c.Type == ClaimTypes.PrimarySid).Value);
var registo = _context.Registos.Find(registoId);
if (registo.IsArranqueActivo)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
public class HasArranqueInactivoHandler : AuthorizationHandler<HasArranqueInactivoRequirement>
{
private readonly NoPaperContext _context;
public HasArranqueInactivoHandler(NoPaperContext context)
{
_context = context;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, HasArranqueInactivoRequirement requirement)
{
// Do something with _context
// Check if the requirement is fulfilled.
var registoId = Convert.ToInt32(context.User.FindFirst(c => c.Type == ClaimTypes.PrimarySid).Value);
var registo = _context.Registos.Find(registoId);
if (!registo.IsArranqueActivo)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
On my page i have it wrotten and it does not trigger the policy handler and i keep getting access denied. Why?
[Authorize(AuthenticationSchemes = "ProductionAuth", Policy = "HasArranqueInactivo")]
EDIT
this is the whole startup
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication()
.AddCookie("ProductionAuth", options =>
{
options.ExpireTimeSpan = TimeSpan.FromDays(1);
options.LoginPath = new PathString("/Production/Index");
options.LogoutPath = new PathString("/Production/Logout");
options.AccessDeniedPath = new PathString("/Production/AccessDenied/");
options.SlidingExpiration = true;
})
.AddCookie("AdministrationAuth", options =>
{
options.ExpireTimeSpan = TimeSpan.FromDays(1);
options.LoginPath = new PathString("/Administration/Index");
options.LogoutPath = new PathString("/Administration/Logout");
options.AccessDeniedPath = new PathString("/Administration/AccessDenied/");
options.SlidingExpiration = true;
});
services.AddAuthorization(options =>
{
options.AddPolicy("HasArranqueActivo", policy =>
policy.Requirements.Add(new HasArranqueActivoRequirement()
));
options.AddPolicy("HasArranqueInactivo", policy =>
policy.Requirements.Add(new HasArranqueInactivoRequirement()
));
});
services.AddSingleton<IFileProvider>(
new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/files")));
services.AddMvc()
.AddRazorPagesOptions(options =>
{
options.AllowAreas = true;
options.Conventions.AuthorizeAreaFolder("Administration", "/Account");
options.Conventions.AuthorizeAreaFolder("Production", "/Account");
})
.AddNToastNotifyToastr(new ToastrOptions()
{
ProgressBar = true,
TimeOut = 3000,
PositionClass = ToastPositions.TopFullWidth,
PreventDuplicates = true,
TapToDismiss = true
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddTransient<IAuthorizationHandler, HasArranqueActivoHandler>();
services.AddRouting(options =>
{
options.LowercaseUrls = true;
options.LowercaseQueryStrings = true;
});
services.AddDbContext<NoPaperContext>(options =>
{
//if(Environment.IsProduction())
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), sqlServerOptionsAction: sqlOptions =>
{
sqlOptions.EnableRetryOnFailure(
maxRetryCount: 2,
maxRetryDelay: TimeSpan.FromSeconds(1),
errorNumbersToAdd: null);
});
//else if(Environment.IsDevelopment())
//options.UseInMemoryDatabase(databaseName: "AbastecimentoDB");
});
services.AddHttpContextAccessor();
services.AddTransient<IComponenteService, ComponenteService>();
services.AddTransient<IReferenciaService, ReferenciaService>();
services.AddTransient<IRegistoService, RegistoService>();
services.AddTransient<IParagemService, ParagemService>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
}
app.UseNToastNotify();
app.UseAuthentication();
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
For HasArranqueActivoHandler, you've added a service registration in ConfigureServices:
services.AddTransient<IAuthorizationHandler, HasArranqueActivoHandler>();
You haven't added a service registration for HasArranqueInactivoHandler. Add the following:
services.AddTransient<IAuthorizationHandler, HasArranqueInactivoHandler>();
Implementations of IAuthorizationHandler are resolved from the DI container, so this missing registration means the authz system cannot handle the HasArranqueInactivoRequirement requirement you've set for the HasArranqueInactivo policy.
I would like to update the DB after a user logged in to my app (using fb) and I am not sure how to use the DbContext within startup.cs.
startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<mysiteContext>(options =>
options.UseSqlServer(_configurationRoot.GetConnectionString("DefaultConnection")));
services.AddAuthentication(options =>
{
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddFacebook(options =>
{
options.AppId = "********";
options.AppSecret = "*********";
options.Events.OnCreatingTicket = context =>
{
var userFbId = context.User.Value<string>("id");
string userProfileImageUrl = $"https://graph.facebook.com/{userFbId}/picture?type=large";
//TODO: Save to DB infromation about the user and update last login date.
//This is where I am having the issue.
UserRepository userRepo = new UserRepository();
//Example how to add information to the claim.
var surname = context.User.Value<string>("last_name");
context.Identity.AddClaim(new Claim(ClaimTypes.Surname, surname));
return Task.FromResult(0);
};
})
.AddCookie();
And my UserRepository.cs:
public class UserRepository
{
private readonly mysiteContext _myDbContext;
private readonly short _languageTypeId;
public UserRepository(mysiteContext ctx)
{
_myDbContext = ctx;
_languageTypeId = Language.GetLanguageTypeId();
}
}
How can I pass mysiteContext to the UserRepository class?
You can do as follows:
services.AddScoped<UserRepository>(); // <-- Register UserRepository here
services.AddAuthentication(options =>
{
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}).AddFacebook(options =>
{
options.AppId = "********";
options.AppSecret = "*********";
options.Events.OnCreatingTicket = context =>
{
........
ServiceProvider serviceProvider = services.BuildServiceProvider();
var userRepository = serviceProvider.GetService<UserRepository>();
// Do whatever you want to do with userRepository here.
.........
return Task.FromResult(0);
};
})
Alternatively you can also get UserRepository instance from context as follows:
var userRepository = context.HttpContext.RequestServices.GetService<UserRepository>();
I had to use my Dapper service inside 'ConfigureServices' section, where 'context' is not available. The easiest way for me was to get the service via 'BuildServiceProvider':
IDapper _dapper = services.BuildServiceProvider().GetService<IDapper>();