I am trying to implement the Okta signin page for use with my aspnet core 2.2 application. After following the quickstart guide for aspnet core, I am able to generate a cookie after I have authenticated. I now want to be able to use this cookie in the form of a Jwt token that can then be used to access API’s. I am able to pull the bearer token from the id token, but when using the bearer in postman, I see a 302 redirect back to the okta signin page. The goal is to be able to leverage the cookie auth I have already obtained. See the code below.
Startup.cs
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddLogging(builder => builder.AddHttp(Configuration.GetSection("HttpLogging"))
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning));
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OktaDefaults.MvcAuthenticationScheme;
})
.AddCookie()
.AddOktaMvc(new OktaMvcOptions
{
OktaDomain = Configuration["okta:domain"],
ClientId = Configuration["okta:clientid"],
ClientSecret = Configuration["okta:clientsecret"],
AuthorizationServerId = null,
OnTokenValidated = async (context) =>
{
}
});
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = "https://{domain}.okta.com";
options.Audience = "";
options.Events = new JwtBearerEvents();
options.Events.OnMessageReceived = async (context) =>
{
var test = context.HttpContext;
};
options.Events.OnAuthenticationFailed = async (context) =>
{
var test = context.HttpContext;
};
});
services.AddAuthorization(options =>
{
var defaultAuthorizationPolicyBuilder = new AuthorizationPolicyBuilder(
CookieAuthenticationDefaults.AuthenticationScheme,
JwtBearerDefaults.AuthenticationScheme);
defaultAuthorizationPolicyBuilder = defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();
options.DefaultPolicy = defaultAuthorizationPolicyBuilder.Build();
});
services.AddMvc(Environment).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;
}
else
{
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseCors(builder => builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
);
app.UseAuthentication(Environment);
app.Use(async (context, next) =>
{
await next();
var bearerAuth = context.Request.Headers["Authorization"]
.FirstOrDefault()?.StartsWith("Bearer ") ?? false;
if (context.Response.StatusCode == 401
&& !context.User.Identity.IsAuthenticated
&& !bearerAuth)
{
await context.ChallengeAsync("OpenIdConnect");
}
});
app.UseStaticFiles()
.UseHttpsRedirection()
.UseMvc();
}
LoginController.cs
[Route("[controller]")]
[ApiController]
public class LoginController : ControllerBase
{
private readonly IHttpContextAccessor _httpContextAccessor;
private ILogger _logger;
public LoginController(
IHttpContextAccessor httpContextAccessor,
ILogger<LoginController> logger)
{
_httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException("httpContextAccessor");
_logger = logger ?? throw new ArgumentNullException("logger");
}
[HttpGet]
public async Task<ActionResult> GetAsync()
{
var context = _httpContextAccessor?.HttpContext;
var result = Ok() as ActionResult;
if(context != null)
{
var token = await context.GetTokenAsync(CookieAuthenticationDefaults.AuthenticationScheme, "id_token");
if(!string.IsNullOrWhiteSpace(token))
_logger?.LogDebug($"Bearer token successfully retrieved and being added to the response body: {token}");
else
_logger?.LogDebug($"No Bearer token was retrieved");
result = Ok(token) as ActionResult;
}
return result;
}
}