I implemented SendGrid in my application, and inside the Account controller I have a method called Register. The method Register allow to the user to signup on the site, inside this method I have the following code:
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var callbackUrl = Url.Action("ConfirmEmail", "Account", new
{
userId = user.Id,
token = code
}, protocol: Request.Scheme);
await _emailSender.SendEmailAsync(user.Email, _localizer["ConfirmYourEmail"], _localizer["ConfirmAccountTemplate", callbackUrl]);
as you can see I generate a confirmation code, and then I created a callBackUrl that the user can find inside the email for confirm the email address. At the end, I call SendEmailAsync which is essentially an implementation of the interface method of Microsoft.AspNetCore.Identity.UI.Services.
Now the main problem is the following: I need to use the same code inside a Repository class, so not inside a Controller, is there a place to store this type of code without create redundance?
PS: I'm sorry if this question seems stupid, but I'm actually a newbie of ASP.NET Core and I want learn to how to create a good project structure.
Thanks in advance for any help.
I need to reuse the method to create the code and send the email
This is a quick mark up I didn't test if this works. You want to make something of the following, and use this in Dependency Injection (DI). You might need to add IUrlHelper and IHttpContextAccessor
public class SomeClass : ISomeClass
{
private HttpContext _ctx;
private IUrlHelper _url;
private IConfiguration _localizer;
private IEmailSender _emailSender;
private UserManager<ApplicationUser> _userManager;
public SomeClass(
IUrlHelper url,
IHttpContextAccessor ctx,
IConfiguration config,
IEmailSender emailSender,
UserManager<ApplicationUser> userManager)
{
_ctx = ctx.HttpContext;
_url = url;
_localizer = config;
_emailSender = emailSender;
_userManager = userManager;
}
public async Task SendEmailWithCode(string email)
{
var user = await _userManager.FindByEmailAsync(email);
var code = await _userManager.GeneratePasswordResetTokenAsync(user);
var callbackUrl = _url.Action(nameof(ResetPassword), "Account", new { userId = user.Id, code }, protocol: _ctx.Request.Scheme);
await _emailSender.SendEmailAsync(user.Email, _localizer["ConfirmYourEmail"], _localizer["ConfirmAccountTemplate"], callbackUrl);
}
}
Related
I have created a hub in my Web API. It is very simple:
public class DashboardHub : Hub
{
public async Task SendMessage(InfoSummary infoSummary)
{
await Clients.All.SendAsync("ReceiveMessage", infoSummary);
}
}
I am trying to send a message to the Hub from a controller in the same Web API when data is updated.
I have seen 100 different answers, and nothing works. Basically my hub object in my controller is null, and I can't seem to get it instantiated.
private readonly IRepository _repo;
private readonly Helpers.Convert _convert;
private readonly CoreContext _context;
private readonly IMapper _mapper;
private readonly NotifyService _service;
private readonly DashboardHub _hub;
public MyController(IRepository repo,
CoreContext context,
IMapper mapper)
{
_convert = new Helpers.Convert(repo, mapper);
_repo = repo;
_context = context;
_mapper = mapper;
_hub = new DashboardHub();
_service = new NotifyService(_hub);
}
[HttpPost("updatestatus")]
public async Task<IActionResult> UpdateStatus(Header header) {
var returnVal = await _repo.ChangeStatus(header.HeaderId, header.Status);
headerSummary = _convert.ToReturnStatusHeader( await _repo.GetHeader(header.HeaderId));
// await _service.SendNotificationAsync(headerSummary);
await _hub.SendMessage(headerSummary);
return Ok(returnVal);
}
I have the
services.AddSignalR();
services.AddScoped(typeof(DashboardHub));
and
endpoints.MapHub<DashboardHub>("/Hubs/DashboardHub");
in the proper sections in the startup.cs file
I know I am missing something very small, but I would love to know what it is.
I have also tried creating a strongly typed hub, but that introduced even more problems.
Thanks in advance.
You have done there or four mistakes.
You don't need this line to be in your ConfigureServices method of Startup.cs. services.AddScoped(typeof(DashboardHub));
Remove it. Just keep services.AddSignalR();
Why are you using new key word, since .net core provide in-built dependency
injection service. Remove below lines.
_hub = new DashboardHub();
_service = new NotifyService(_hub);
Instead create a new interface INotifyService.cs for NotifyService.cs.
Register this service in ConfigureServices method of Startup.cs.
services.AddScoped<INotifyService, NotifyService>();
Your MyController.cs should be like below
Add this line.
using Microsoft.AspNetCore.SignalR;
private readonly IRepository _repo;
private readonly Helpers.Convert _convert;
private readonly CoreContext _context;
private readonly IMapper _mapper;
private readonly INotifyService _service;
private readonly IHubContext<DashboardHub> _hubContext
public MyController(IRepository repo, CoreContext context, IMapper mapper,INotifyService service,IHubContext<DashboardHub> hubContext)
{
_convert = new Helpers.Convert(repo, mapper);
_repo = repo;
_context = context;
_mapper = mapper;
_service = service;
_hubContext = hubContext;
}
[HttpPost("updatestatus")]
public async Task<IActionResult> UpdateStatus(Header header) {
var returnVal = await _repo.ChangeStatus(header.HeaderId, header.Status);
headerSummary = _convert.ToReturnStatusHeader( await _repo.GetHeader(header.HeaderId));
// await _service.SendNotificationAsync(headerSummary);
await hubContext.Clients.All.SendAsync("ReceiveMessage", headerSummary);
return Ok(returnVal);
}
Use same concept if you are sending messages inside your NotifyService.cs.
Well, I feel like a complete and utter newb. The fix is very simple. You must add the using statement telling the controller you want to use SignalR. OMG.. I am almost too embarrassed to put this up, but hope it will help someone else.
FIX:
using Microsoft.AspNetCore.SignalR;
:facepalm
What you could do is inject your hub using dependency injection in your controller. You can't just instanciate the hub in the controller like you are doing, and I would change it to a Singleton also.
services.AddSingleton(typeof(DashboardHub));
internal DashboardHub DashboardHub
{
get
{
return this.HttpContext.RequestServices.GetRequiredService<DashboardHub>();
}
}
I'm currently following a .Net Core Angular 8 tutorial in Udemy. I'm able do get/post requests in Postman and I can also see what I've posted in a .db file using sqlite as my database and viewing the data through Db Browser. Everything seems to be working great but is all for nothing if I can't comprehend what's going on in some areas of the application. I would really appreciate it if someone could help me answer a few questions.
My entire project is in GitHub: https://github.com/cjtejada/ASP.NetCoreAngular8/tree/master/DatingApp.API
Problem 1: I have the following the following controller:
[Route("api/[controller]")]
[ApiController]
public class AuthController : ControllerBase
{
private readonly IAuthRepository _repo;
private readonly IConfiguration _config;
public AuthController(IAuthRepository repo, IConfiguration config)
{
_repo = repo;
_config = config;
}
[HttpPost("register")]
public async Task<IActionResult> Register(UserForRegisterDto userForRegisterDto)
{
// validate request
userForRegisterDto.Username = userForRegisterDto.Username.ToLower();
if (await _repo.UserExists(userForRegisterDto.Username))
return BadRequest("User already exists");
var userToCreate = new User
{
Username = userForRegisterDto.Username
};
var createdUser = await _repo.Register(userToCreate, userForRegisterDto.Password);
return StatusCode(201);
}
}
I know that when the client makes a request to register, the register() method will be called and the Username that gets passed in will set the Username from DTO userForRegisterDto. After this then we call method UserExists() to check if the user exists in our database.
Question 1:
How is _repo aware of the logic in method UserExists() when it is only using the interface IAuthRepository? I know that IAuthRepository and class AuthRepository are somehow linked but I don't see anywhere in the app where Constructor DI is happening. My suspicion is that it has something to do with this line in startup.cs under the ConfigureServices method :
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<DataContext>(x => x.UseSqlite(Configuration.GetConnectionString("DefaultConnection")));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddCors();
services.AddScoped<IAuthRepository, AuthRepository>(); //<---- This Line
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => {
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration.GetSection("AppSettings:Token").Value)),
ValidateIssuer = false,
ValidateAudience = false
};
});
}
After these two are "linked up", then the UserExists() method can be accessed through the AuthRepository class:
public class AuthRepository : IAuthRepository
{
private readonly DataContext _context;
public AuthRepository(DataContext context)
{
_context = context;
}
public async Task<User> Login(string username, string password)
{
}
private bool VerifyPasswordHash(string password, byte[] passwordHash, byte[] passwordSalt)
{
}
public async Task<User> Register(User user, string password)
{
byte[] passwordHash, passwordSalt;
CreatePasswordHash(password, out passwordHash, out passwordSalt);
user.PasswordHash = passwordHash;
user.PasswordSalt = passwordSalt;
await _context.Users.AddAsync(user);
await _context.SaveChangesAsync();
return user;
}
private void CreatePasswordHash(string password, out byte[] passwordHash, out byte[] passwordSalt)
{
}
public async Task<bool> UserExists(string username)
{
if (await _context.Users.AnyAsync(x => x.Username == username))
return true;
return false;
}
}
I've been reading about the AddScoped method and what it does but this is not clear to me that this is the case. Any clarification as to how this works would be great.
Problem 2:
This one is more or less the same. If we keep following the path of the request we will hit the register() method in the AuthRepository class.
Question 2:
How does this class have access to the properties of DataContext _context when I also can't spot any instances of constructor DI anywhere?
Here are the rest of my project files if needed:
Startup.cs
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.AddDbContext<DataContext>(x => x.UseSqlite(Configuration.GetConnectionString("DefaultConnection")));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddCors();
services.AddScoped<IAuthRepository, AuthRepository>();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => {
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration.GetSection("AppSettings:Token").Value)),
ValidateIssuer = false,
ValidateAudience = false
};
});
}
// 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.UseHsts();
}
//app.UseHttpsRedirection();
app.UseCors(x => x.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
app.UseAuthentication();
app.UseMvc();
}
}
DataContext.cs
public class DataContext : DbContext
{
public DataContext(DbContextOptions<DataContext> options) : base (options){}
public DbSet<Value> Values { get; set; }
public DbSet<User> Users { get; set; }
}
Any clarifications and suggestions are greatly appreciated. Thanks, all.
You are correct. The line services.AddScoped<IAuthRepository, AuthRepository>(); simply instructs the ASP.NET Core service container to substitute an instance of concrete class AuthRepository wherever it sees a reference to IAuthRepository at runtime.
The various Add* methods all do the same thing under the hood regarding registering the mapping of interfaces => classes, the key difference is the scope of the created class, i.e. how long it persists for:
AddScoped classes will be created at the beginning of every request to the server, and destroyed at the end of every request. In other words, every request results in a new instance of that class being created.
AddSingleton classes are created when your ASP.NET Core application starts up, and are destroyed when it shuts down. In other words, only a single instance of that class exists within your application.
AddTransient classes are recreated whenever they are requested. In other words, if a page on your site used the same service transient twice, there would be two instances created. (Contrast this with a scoped service, where only a single instance would be created, as each page is a single request.)
A fuller explanation, including examples: https://stackoverflow.com/a/38139500/70345
In order to fulfill (1) by creating an instance of your class AuthRepository, the service container needs to call that class's constructor. The container inspects your class to find the first public constructor and retrieves any arguments to that constructor, in this case an instance of the DataContext class. The container then searches its internal class mappings for that class and, because you have registered that mapping via services.AddDbContext<DataContext>(...), is able to construct and return the class instance. Thus it's able to pass that instance to AuthRepository, so AuthRepository is constructed successfully.
The AddDbContext method is simply a wrapper around AddScoped, that performs some additional scaffolding to allow Entity Framework DbContexts to work correctly.
For the official explanation, refer to Microsoft's official page on DI and IoC.
Question 1 - You've right this line in Startup.cs provide creating a new object AuthRepository. For this example you must to know that DI container creates an AuthRepository object for you based on the interface and his own implementation and you only need to pass an interface in properly constructor. AddScope() is related with lifetime of created objects. When you register object by method AddScope() then the object will be created for a single request and after the request, the object will be disposed.
Question 2 - Your dbContext is registered in DI container. AddDbContext() is a specific extension method provided to registration of entity framework dbContextes. This line of code registers your dbContext with connection strings got from the appSetting.json file.
services.AddDbContext<DataContext>(x =>
x.UseSqlite(Configuration.GetConnectionString("DefaultConnection")));
This DbContext is injected into the constructor of the AuthRepository class and when you use this class DI container created DbContext instance for you.
private readonly DataContext _context;
public AuthRepository(DataContext context)
{
_context = context;
}
I have this code that is supposed to set claims for a user. It works fine when I use identity and the default login. However, when I use jwt as authentication in another application, I don't have ApplicationUser as my ApplicationUser is stored in the other application that authenticates the user. How can I customize this code so that it works with jwt?
private readonly SignInManager<TIdentityUser> _signInManager;
public CustomClaimsCookieSignInHelper(SignInManager<TIdentityUser> signInManager)
{
_signInManager = signInManager;
}
public async Task SignInUserAsync(TIdentityUser user, bool isPersistent, IEnumerable<Claim> customClaims)
{
var claimsPrincipal = await _signInManager.CreateUserPrincipalAsync(user);
var identity = claimsPrincipal.Identity as ClaimsIdentity;
var claims = (from c in claimsPrincipal.Claims select c).ToList();
var savedClaims = claims;
if (customClaims != null)
{
identity.AddClaims(customClaims);
}
await _signInManager.Context.SignInAsync(IdentityConstants.ApplicationScheme,
claimsPrincipal,
new AuthenticationProperties { IsPersistent = isPersistent });
}
I guess my main intention is to set my users claims in the httpcontext and not in a cookie and I want to do that without using identity.
EDIT:
My application structure
AuthenticationApp (server)
Responsible for authenticating users
Generates and Decodes Jwt
Checks if the user has the appropriate roles and returns true/false via rest api
MainApp (client)
Makes an api call to AuthenticationApp
Does not use identity at all
Sends Jwt everytime I need to check the role of the user
I understand that I will be able to decode the jwt client side. However, I do not know where I can store the decoded jwt details so that I can use it in the view. My initial idea was to use Httpcontext like normal applications that user Identity. However, I am stuck with the code above.
For sharing the Identity information between Controller and View, you could sign the User information by HttpContext.SignInAsync.
Try steps below to achieve your requirement:
Controller Action
public async Task<IActionResult> Index()
{
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme, ClaimTypes.Name, ClaimTypes.Role);
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, "edward"));
identity.AddClaim(new Claim(ClaimTypes.Name, "edward zhou"));
//add your own claims from jwt token
var principal = new ClaimsPrincipal(identity);
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal, new AuthenticationProperties { IsPersistent = true });
return View();
}
View
#foreach (var item in Context.User.Claims)
{
<p>#item.Value</p>
};
To make above code work, register Authentication in Startup.cs
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)
{
//your rest code
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//your rest code
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
I have a ASP.NET Core 1.0 Solution with 3 projects (Web, Console Application, DataAccessLayer).
I use ASP.NET Core Identity and Entity Framework Core (SQL Server - Code First).
In my Console Application (Used for background tasks), I want to create users, but how I can have access to UserManager object in a Console Application (Or in a .NET Core Class Library) ?
In a controller class, it's easy with Dependency Injection :
public class AccountController : Controller {
private readonly UserManager<ApplicationUser> _userManager;
public AccountController(UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager)
{
_userManager = userManager;
}
//...
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Register(RegisterViewModel model)
{
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
var result = await _userManager.CreateAsync(user, model.Password);
//...
}
How I can do the equivalent in a Console Core Application ?
Thanks to Tseng's answer I ended up with this code. Just in case if someone would need:
public class Program
{
private interface IUserCreationService
{
Task CreateUser();
}
public static void Main(string[] args)
{
var services = new ServiceCollection();
services.AddDbContext<ApplicationDbContext>(
options =>
{
options.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=my-app-db;Trusted_Connection=True;MultipleActiveResultSets=true");
});
// Authentification
services.AddIdentity<ApplicationUser, IdentityRole>(opt =>
{
// Configure identity options
opt.Password.RequireDigit = false;
opt.Password.RequireLowercase = false;
opt.Password.RequireUppercase = false;
opt.Password.RequireNonAlphanumeric = false;
opt.Password.RequiredLength = 6;
opt.User.RequireUniqueEmail = true;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddScoped<IUserCreationService, UserCreationService>();
// Build the IoC from the service collection
var provider = services.BuildServiceProvider();
var userService = provider.GetService<IUserCreationService>();
userService.CreateUser().GetAwaiter().GetResult();
Console.ReadKey();
}
private class UserCreationService : IUserCreationService
{
private readonly UserManager<ApplicationUser> userManager;
public UserCreationService(UserManager<ApplicationUser> userManager)
{
this.userManager = userManager;
}
public async Task CreateUser()
{
var user = new ApplicationUser { UserName = "TestUser", Email = "test#example.com" };
var result = await this.userManager.CreateAsync(user, "123456");
if (result.Succeeded == false)
{
foreach (var error in result.Errors)
{
Console.WriteLine(error.Description);
}
}
else
{
Console.WriteLine("Done.");
}
}
}
}
In my Console Application (Used for background tasks), I want to create users, but how I can have access to UserManager object in a Console Application (Or in a .NET Core Class Library) ?
Same as you do it in ASP.NET Core. You just need to bootstrap it yourself. Inside your Main (which is the console applications composition root - the earliest point where you can set up your object graph).
Here you create a ServiceCollection instance, register the services and build the container, then resolve your app entry point. From there, anything else goes via DI.
public static int Main(string[] args)
{
var services = new ServiceCollection();
// You can use the same `AddXxx` methods you did in ASP.NET Core
services.AddIdentity();
// Or register manually
services.AddTransient<IMyService,MyService();
services.AddScoped<IUserCreationService,UserCreationService>();
...
// build the IoC from the service collection
var provider = services.BuildServiceProvider();
var userService = provider.GetService<IUserCreationService>();
// we can't await async in Main method, so here this is okay
userService.CreateUser().GetAwaiter().GetResult();
}
public class UserCreationService : IUserCreationService
{
public UserManager<ApplicationUser> userManager;
public UserCreationService(UserManager<ApplicationUser> userManager)
{
this.userManager = userManager;
}
public async Task CreateUser()
{
var user = new ApplicationUser { UserName = "TestUser", Email = "test#example.com" };
var result = await _userManager.CreateAsync(user, model.Password);
}
}
In practice the first class you resolve wouldn't be your UserCreationService but some MainApplication class, which is the core of your application and responsible for keeping the application alive as long as the operation happens, i.e. if its a background worker you run some kind of host (Azure Web Job Host etc.) which keeps the application running so it can receive events from outside (via some message bus) and on each event starts a specific handler or action, which in turn resolves other services etc.
I know this answer is late, but other people might benefit.
You are seriously overcomplicating things using services etc.
You can just do:
var userStore = new UserStore<ApplicationUser>(new ApplicationDbContext());
var manager = new ApplicationUserManager(userStore);
var result = await manager.Create(user, password);
If you still want all the password validation functionality just add it to the constructor of ApplicationUserManager
I have a WebAPI 2.1 application and I am having a problem with User Registration. I placed a breakpoint on the first line of the Register method but it is not reached. Instead it fails in the area below:
public ApplicationUserManager UserManager
{
get
{
var a = Request; // this is null !!
return _userManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
private set
{
_userManager = value;
}
}
[AllowAnonymous]
[Route("Register")]
[ValidateModel]
public async Task<IHttpActionResult> Register(RegisterBindingModel model)
{
var user = new ApplicationUser() { // <<<<< Debug breakpoint here never reached
Email = model.Email,
FirstName = model.FirstName,
LastName = model.LastName,
OrganizationId = 1,
OrganizationIds = "1",
RoleId = (int)ERole.Student,
SubjectId = 1,
SubjectIds = "1",
UserName = model.UserName
};
System.ArgumentNullException was unhandled by user code
HResult=-2147467261
Message=Value cannot be null.
Parameter name: request
Source=System.Web.Http.Owin
ParamName=request
StackTrace:
at System.Net.Http.OwinHttpRequestMessageExtensions.GetOwinContext(HttpRequestMessage request)
at WebRole.Controllers.AccountController.get_UserManager() in c:\G\abr\WebRole\Controllers\Web API - Data\AccountController.cs:line 50
at WebRole.Controllers.AccountController.Dispose(Boolean disposing) in c:\G\ab\WebRole\Controllers\Web API - Data\AccountController.cs:line 376
at System.Web.Http.ApiController.Dispose()
at System.Web.Http.Cors.AttributeBasedPolicyProviderFactory.SelectAction(HttpRequestMessage request, IHttpRouteData routeData, HttpConfiguration config)
at System.Web.Http.Cors.AttributeBasedPolicyProviderFactory.GetCorsPolicyProvider(HttpRequestMessage request)
InnerException:
If anyone could give me any advice on where I could look to help solve this problem I would much appreciate it.
In particular can some explain to me the flow of how a request is handled in this configuration. I find it pretty confusing and I would like to know how the WebAPI and Owin fit together. Not knowing this is making it me difficult for me to understand the problem.
Thanks.
For reference here is my WebAPI start up class:
public partial class Startup
{
public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }
public static string PublicClientId { get; private set; }
// For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context and user manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Configure the application for OAuth based flow
PublicClientId = "self";
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
AllowInsecureHttp = true
};
// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);
}
}
Update 1 - question correct after Darin's comments. The problem is not in the constructor.
Update 2 - Dispose Method:
protected override void Dispose(bool disposing)
{
if (disposing)
{
UserManager.Dispose();
}
base.Dispose(disposing);
}
Update 3 - Added the /Register method to show where I have a breakpoint (that's never reached)
There is no check for a null _userManager in your dispose method but the backing field can still be null. Also you access the UserManager property instead of using the backing field directly. So every time _userManager is null and the AccountController gets disposed the UserManager will try to create a new OwinContext. And that will fail.
Change your dispose method to:
protected override void Dispose(bool disposing)
{
if (disposing && _userManager != null)
{
_userManager.Dispose();
_userManager = null
}
base.Dispose(disposing);
}
The problem I have is in the Account constructor
The HTTP Context is not available in a controller constructor and this is by design. The earliest point in the execution where you can access it is after the Initialize method:
protected override void Initialize(HttpControllerContext controllerContext)
{
base.Initialize(controllerContext);
// This is the earliest stage where you can access the HTTP context (request, response, ...).
}