I am connecting to google android managment API sucessfully and returning data as expected when ussing swagger. The example I followed is Google API Call .net core
The issue I am having is when I call my middle ware API from my front end I get a cors error:
Access to XMLHttpRequest at
'https://accounts.google.com/o/oauth2/v2/auth?CLINET_ID_REMOVED'
(redirected from 'https://localhost:44347/api/Device/Get') from origin
'http://localhost:3000' has been blocked by CORS policy: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
Once I login by clicking the link the front end works as expected. How can I get the login to popup if the user is not yet logged in?
What am I missing in this implamentation? The example at Google.Apis.Auth.AspNetCore3.IntegrationTests is for MVC (which I am not using) and contains some generic login pages, do I need to implament that too?
StartUp.cs
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
// Add Cors
services.AddCors();
//services.AddCors(o => o.AddPolicy("MyPolicy", builder =>
//{
// builder.AllowAnyOrigin()
// .AllowAnyMethod()
// .AllowAnyHeader();
//}));
// This configures Google.Apis.Auth.AspNetCore3 for use in this app.
services
.AddAuthentication(o =>
{
// This forces challenge results to be handled by Google OpenID Handler, so there's no
// need to add an AccountController that emits challenges for Login.
o.DefaultChallengeScheme = GoogleOpenIdConnectDefaults.AuthenticationScheme;
// This forces forbid results to be handled by Google OpenID Handler, which checks if
// extra scopes are required and does automatic incremental auth.
o.DefaultForbidScheme = GoogleOpenIdConnectDefaults.AuthenticationScheme;
// Default scheme that will handle everything else.
// Once a user is authenticated, the OAuth2 token info is stored in cookies.
o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie()
.AddGoogleOpenIdConnect(options =>
{
options.ClientId = authClientID;
options.ClientSecret = authClientSecret;
});
//services.AddDataProtection();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "AndroidManagmentAPI", Version = "v1" });
});
}
Get Enterprise Method
// GET: api/<EnterpriseController>
[HttpGet("Get")]
[Authorize]
[GoogleScopedAuthorize(AndroidManagementService.ScopeConstants.Androidmanagement)]
public async Task<Enterprise> Get([FromServices] IGoogleAuthProvider auth)
{
SignupData signupData = JsonConvert.DeserializeObject<SignupData>(GetEnvirmentVarable(Utilities.SignupDetails));
Enterprise enterprise = new Enterprise();
enterprise.Name = signupData.EnterpriseName;
var er = await GetEnterprisesResource(auth);
var result = er.Get(enterprise.Name);
var ent = result.Execute();
return ent;
}
Related
About OAuth.
Frontend SPA react
MVC OAuth backend, signs user's into 3rd party providers, works nicely, return token.
from my SPA I can do window.open and redirect the user to a sign-in page, NB: has to be a new window as xframeoptions is set to deny.
How do I return the token & correlate with SPA, as they are in separate windows/sessions?
options I'm looking at
content security policy - set the caller's domain
set same site cookie
Using aspnet-contrib/AspNet.Security.OAuth.Providers
Samples
Startup.cs
public class Startup
{
private const string policyName = "Cors";
public Startup(IConfiguration configuration, IHostEnvironment hostingEnvironment)
{
Configuration = configuration;
HostingEnvironment = hostingEnvironment;
}
public IConfiguration Configuration { get; }
private IHostEnvironment HostingEnvironment { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddRouting();
services.AddCors(opt =>
{
opt.AddPolicy(name: policyName, builder =>
{
builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyOrigin()
.AllowAnyMethod();
});
});
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.LoginPath = "/signin";
options.LogoutPath = "/signout";
})
.AddGitHub(options =>
{
options.ClientId = Configuration["GitHub:ClientId"];
options.ClientSecret = Configuration["GitHub:ClientSecret"];
options.Scope.Add("user:email");
options.Scope.Add("read:org");
options.Scope.Add("workflow");
options.SaveTokens=true;
});
services.AddMvc();
}
public void Configure(IApplicationBuilder app)
{
if (HostingEnvironment.IsDevelopment())
{
// IdentityModelEventSource.ShowPII = true;
}
// Required to serve files with no extension in the .well-known folder
//var options = new StaticFileOptions()
//{
// ServeUnknownFileTypes = true,
//};
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
});
app.UseCors(policyName);
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
});
Authentication Controller
public class AuthenticationController : Controller
{
[HttpGet("~/signin")]
public async Task<IActionResult> SignIn() => View("SignIn", await HttpContext.GetExternalProvidersAsync());
[HttpPost("~/signin")]
public async Task<IActionResult> SignIn([FromForm] string provider)
{
// Note: the "provider" parameter corresponds to the external
// authentication provider choosen by the user agent.
if (string.IsNullOrWhiteSpace(provider))
{
return BadRequest();
}
if (!await HttpContext.IsProviderSupportedAsync(provider))
{
return BadRequest();
}
// Instruct the middleware corresponding to the requested external identity
// provider to redirect the user agent to its own authorization endpoint.
// Note: the authenticationScheme parameter must match the value configured in Startup.cs
return Challenge(new AuthenticationProperties { RedirectUri = "/" }, provider);
}
[HttpGet("~/signout")]
[HttpPost("~/signout")]
public IActionResult SignOutCurrentUser()
{
// Instruct the cookies middleware to delete the local cookie created
// when the user agent is redirected from the external identity provider
// after a successful authentication flow (e.g Google or Facebook).
return SignOut(new AuthenticationProperties { RedirectUri = "/" },
CookieAuthenticationDefaults.AuthenticationScheme);
}
}
Home Controller
public class HomeController : Controller
{
public async Task<IActionResult> IndexAsync()
{
var accessToken = await HttpContext.GetTokenAsync("GitHub", "access_token");
var refreshToken = await HttpContext.GetTokenAsync("GitHub", "refresh_token");
return View();
}
}
Home Page (Index.cshtml)
<div class="jumbotron">
#if (User?.Identity?.IsAuthenticated ?? false)
{
<h1>Welcome, #User.Identity.Name</h1>
<p>
#foreach (var claim in Context.User.Claims)
{
<div><code>#claim.Type</code>: <strong>#claim.Value</strong></div>
}
</p>
<a class="btn btn-lg btn-danger" href="/signout?returnUrl=%2F">Sign out</a>
}
else
{
<h1>Welcome, anonymous</h1>
<a class="btn btn-lg btn-success" href="/signin?returnUrl=%2F">Sign in</a>
}
</div>
Thanks for looking
It seems (correct me if I'm mistaken) that the main issue is launching the window for github auth and sending that token back to your site which is a different window (i.e. the parent window of the popup).
One option is to set up your auth request's redirect_uri parameter so that the 3rd party identity provider redirects back to a URL on your site (within the popup window), i.e. your ~/signin endpoint. This allows your server-side to grab hold of the tokens and do things like create a session, store a cookie, etc. Cookies set within the popup window will be available to your site in the original window (assuming it's the same domain) once the parent window has refreshed.
Next, once the popup window has been redirected back to your ~/signin endpoint and you've created the session or stored a cookie, etc, you may wish to close that popup and refresh the parent window so that it recognises the cookie / new session. You can do this by returning a page from the ~/signin request (still inside the popup) which includes the following JavaScript:
window.opener.document.location.reload();
// alternatively send the user to an authenticated homepage:
window.opener.document.location.href = '/signed-in-user-homepage';
// and then close the popup
window.close();
I don't think it's your goal but for completeness, if you wish to perform OAuth authentication/authorisation from the SPA itself, so the server side doesn't get the tokens, you may wish to let a Javascript library like oidc-client do the heavy lifting. This launches its own window to perform authentication and hands back the token to the calling SPA itself. These tokens are not visible to the server side.
One resource which really helped me figure this out was the IdentityServer4 quickstart for JavaScript clients, worth stepping through if this is your use case:
OpenID Connect auth from JavaScript clients quickstart
Sample code for the above quickstart
Once you've got a token on the client side (i.e. in JavaScript), you could pass it to the server side to use to make requests on behalf of the user but this isn't good practice as it impersonation rather than properly delegated authorisation, and you'd need to work out what to do when the access token expires (passing the refresh token to the server side effectively allows your server to impersonate the user indefinitely).
My preference is to allow the server-side to perform an auth-code authorisation flow using AspNet.Security.OAuth.Providers, receive the auth code to the ~/signin page, perform the back channel request to get the tokens, use the identity information to create my own profile for the user and perform requests on behalf of the user using authorisation delegated to my service.
Let me know if any of this needs more explaining but hope it's useful as-is.
I'm trying out OpenIddict 3.0 for use in a SSO app. I followed the steps in the documentation, created an Authorize controller, and added a test application. When I try to connect to authorize I get this exception:
System.InvalidOperationException: The authorization request was not handled. To handle authorization requests, create a class implementing 'IOpenIddictServerHandler' and register it using 'services.AddOpenIddict().AddServer().AddEventHandler()'.
Alternatively, enable the pass-through mode to handle them at a later stage.
I can't find anything in the documentation or sample apps that explains what this means. What am I missing?
Here's my code so far. In Startup.cs:
services.AddOpenIddict()
.AddCore(o =>
{
o.UseEntityFrameworkCore().UseDbContext<ApplicationDbContext>();
})
.AddServer(o =>
{
o.SetTokenEndpointUris("/connect/token");
o.SetAuthorizationEndpointUris("/connect/authorize");
o.AllowAuthorizationCodeFlow();
o.RegisterScopes(OpenIddictConstants.Scopes.Email);
o.AcceptAnonymousClients();
o.AddDevelopmentEncryptionCertificate()
.AddDevelopmentSigningCertificate();
o.UseAspNetCore()
.EnableTokenEndpointPassthrough()
.DisableTransportSecurityRequirement();
})
.AddValidation(o =>
{
o.UseLocalServer();
o.UseAspNetCore();
});
And test app description:
var descriptor = new OpenIddictApplicationDescriptor
{
ClientId = "test-app",
DisplayName = "Test Application",
PostLogoutRedirectUris = { new Uri("https://oidcdebugger.com/debug") },
RedirectUris = { new Uri("https://oidcdebugger.com/debug") }
};
I'm testing with the OpenID Connect debugger.
To handle authorization requests in a MVC controller, you must tell OpenIddict's ASP.NET Core host to use the pass-through mode, exactly like what you did for the token endpoint:
services.AddOpenIddict()
.AddServer(options =>
{
options.UseAspNetCore()
.EnableAuthorizationEndpointPassthrough() // Add this line.
.EnableTokenEndpointPassthrough()
.DisableTransportSecurityRequirement();
});
I am facing issues while implementing external login in asp.net core 2.2 (mvc) without using identity. After signing in to google it redirect back to callback url that is throwing exception as attached in the image below.
Exception: The oauth state was missing or invalid.
Unknown location
Exception: An error was encountered while handling the remote login.
Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler.HandleRequestAsync()
For more detailed steps that I did, please check here
Below is Startup.cs settings
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services
.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.Cookie.IsEssential = true;
})
.AddGoogle(options =>
{
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.ClientId = Configuration["Authentication:Google:ClientId"];
options.ClientSecret = Configuration["Authentication:Google:ClientSecret"];
options.CallbackPath = "/externallogincallback";
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
Below is my HomeController.cs settings
//Action to issue a challange to google login
public IActionResult Google(string provider)
{
provider = "Google";
//Issue a challenge to external login middleware to trigger sign in process
//return new ChallengeResult(provider);
var authenticationProperties = new AuthenticationProperties
{
RedirectUri = Url.Action("externallogincallback")
};
return Challenge(authenticationProperties, "Google");
}
//Callback action to retrive signin user details
[HttpGet("externallogincallback", Name = "externallogincallback")]
[AllowAnonymous]
public Task<IActionResult> externallogincallback(string returnUrl = null, string remoteError = null)
{
//Here we can retrieve the claims
var result = HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return null;
}
In Google console setting
Authorized redirect URIs
For use with requests from a web server. This is the path in your application that users are redirected to after they have authenticated with Google. The path will be appended with the authorization code for access. Must have a protocol. Cannot contain URL fragments or relative paths. Cannot be a public IP address.
https://localhost:44379/externallogincallback
It is a bit confusing...
The options.CallbackPath is not the path to your Controller/Action. It just must be the same as registered in your 3rd party provider (Google, or so...). By default it is signin-google, and this callback handler is taken by IdentityServer.
The callback externallogincallback is actually set in the ChallengeResult.
So, if you set the options.CallbackPath and Challenge(RediretUrl) as the same, which means it has two hanlders with same name/route, ASP.NET will run in error.
Remove callbackpath from setting
options.CallbackPath = "/externallogincallback";
You have probably used routing in the startup and you need to define the following routing for this url
routes.MapRoute(
name: "GoogleResponse",
template: "externallogincallback ",
defaults: new { controller = "Home", action = "externallogincallback" });
As was mentioned removing options.CallbackPath is the right answer. It is because options.CallbackPath serves not as your API endpoint that will continue to execute after login rather than it serves as endpoint for some internal auth logic.
More details in my answer here https://stackoverflow.com/a/61950614/9547346
I had same problem before, it was port mismatch with redirect url.
Check your lauchSetting.json's default port number.
I have an ASP.NET Core 2.x project with the following configuration:
services
.AddAuthentication(options => options.DefaultScheme = CookieAuthenticaitonDefaults.AuthenticationScheme)
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddFacebook(ConfigureFacebook);
Predictably, when I call from one of my actions:
return Challenge(new AuthenticationProperties { RedirectUri = "/test" }, "Facebook");
... Then, I get navigated through the Facebook OAuth sequence. When I find my way back to my app, HttpContext.User.Identity is populated with the relevant details:
User.Identity.Name - The Facebook user name.
User.Identity.AuthenticationType - The string "Facebook".
User.Identity.IsAuthenticated - true.
This is all well and as is expected. However, if I add to my application configuration the following
services.AddIdentity<MyUserType, MyRoleType>()
.AddEntityFrameworkStores<MyDbContext>();
Suddenly, the OAuth flow ends in User.Identity being anonymous without anything else changing. If we drill into IdentityServiceCollectionExtensions.cs, we find:
options.DefaultAuthenticateScheme =
IdentityConstants.ApplicationScheme; options.DefaultChallengeScheme =
IdentityConstants.ApplicationScheme; options.DefaultSignInScheme =
IdentityConstants.ExternalScheme;
among other things...
What is going on here? Why is Identity interfering with the Cookie process, and what is the correct way to get the User returned from an OAuth provider?
For combining OAuth and Asp.Net Core Identity, you need to configure the facebookOptions.SignInScheme with CookieAuthenticationDefaults.AuthenticationScheme.
Try code below:
services
.AddAuthentication(options => options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddFacebook(facebookOptions =>
{
facebookOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
facebookOptions.AppId = "xx";
facebookOptions.AppSecret = "xxx";
});
When combining ASP.NET Identity and OAuth, certain considerations need to be made:
Configuring the services:
Adding AddCookie(CookieAuthenticationDefaults.AuthenticationScheme) is no longer necessary because Identity adds its own cookie handlers.
Getting the external user as a ClaimsPrincipal:
If you want the external user to be populated under HttpContext.User, do the following:
.AddFacebook(options => {
options.SignInScheme = IdentityConstants.ApplicationScheme;
})
After being redirected to the RedirectUri in your challenge's AuthenticationProperties, your HttpContext.User will be populated.
Getting the external user as ExternalLoginInfo:
This is preferred if you need to know things about the user such as:
From what provider did they come?
What is their unique key on the provider?
Your services should be configured like so:
services.AddAuthentication()
.AddFacebook(options =>
{
options.AppId = "";
options.AppSecret = "";
});
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<MyDbContext>();
In your login controller, inject SignInManager<TUser> in:
public DefaultController(SIgnInManager<IdentityUser> signInManager)
And in your challenge action, use ConfigureExternalAuthenticationProperties to get the challenge properties:
public IActionResult LoginExternal() {
var props = SignInManager.ConfigureExternalAuthenticationProperties("Facebook", "/");
return Challenge(props, "Facebook");
}
In your return action, use GetExternalLoginInfoAsync to get the external details about the user:
public async Task<IActionResult> LoginCallback() {
var loginInfo = await SignInManager.GetExternalLoginInfoAsync();
// This object will tell you everything you need to know about the incoming user.
}
I have the following application at GitHub and have deployed it to https://stratml.services on an Azure App Service with Authentication defined as Microsoft Account with anymous requests requiring a Microsoft Account sign in. In "prod" this challenge occurs, however https://stratml.services/Home/IdentityName returns no content.
I have been following this and this however I do not want to use EntityFramework and from the latter's description it seems to imply if I configure my Authentication scheme correctly I do not have to.
This following code is in my Start class:
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = MicrosoftAccountDefaults.AuthenticationScheme;
}).AddMicrosoftAccount(microsoftOptions =>
{
microsoftOptions.ClientId = Configuration["Authentication:AppId"];
microsoftOptions.ClientSecret = Configuration["Authentication:Key"];
microsoftOptions.CallbackPath = new PathString("/.auth/login/microsoftaccount/callback");
});
Update: Thanks to the first answer I was able to get, it now authorizes to Microsoft and attempts to feedback to my application however I receive the following error:
InvalidOperationException: No IAuthenticationSignInHandler is configured to handle sign in for the scheme: Cookies
Please visit https://stratml.services/Home/IdentityName and the GitHub has been updated.
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = MicrosoftAccountDefaults.AuthenticationScheme;
}).AddCookie(option =>
{
option.Cookie.Name = ".myAuth"; //optional setting
}).AddMicrosoftAccount(microsoftOptions =>
{
microsoftOptions.ClientId = Configuration["Authentication:AppId"];
microsoftOptions.ClientSecret = Configuration["Authentication:Key"];
});
I have checked this issue on my side, based on my test, you could confgure your settings as follows:
Under the ConfigureServices method, add the cookie and MSA authentication services.
services.AddAuthentication(options =>
{
options.DefaultChallengeScheme = MicrosoftAccountDefaults.AuthenticationScheme;
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(option =>
{
option.Cookie.Name = ".myAuth"; //optional setting
})
.AddMicrosoftAccount(microsoftOptions =>
{
microsoftOptions.ClientId = Configuration["Authentication:AppId"];
microsoftOptions.ClientSecret = Configuration["Authentication:Key"];
});
Under the Configure method, add app.UseAuthentication().
TEST:
[Authorize]
public IActionResult Index()
{
return Content(this.User.Identity.Name);
}
When I checking your online website, I found that you are using the Authentication and authorization in Azure App Service and Authenticate with Microsoft account.
AFAIK, when using the app service authentication, the claims could not be attached to current user, you could retrieve the identity name via Request.Headers["X-MS-CLIENT-PRINCIPAL-NAME"] or you could follow this similar issue to manually attach all claims for current user.
In general, you could either manually enable authentication middle-ware in your application or just leverage the app service authentication provided by Azure without changing your code for enabling authentication. Moreover, you could Remote debugging web apps to troubleshoot with your application.
UPDATE:
For enable the MSA authentication in my code and test it when deployed to azure, I disabled the App Service Authentication, then deployed my application to azure web app. I opened a new incognito window and found that my web app could work as expected.
If you want to simulate the MSA login locally and use Easy Auth when deployed to azure, I assumed that you could set a setting value in appsettings.json and manually add the authentication middle-ware for dev and override the setting on azure, details you could follow here. And you could use the same application Id and configure the following redirect urls:
https://stratml.services/.auth/login/microsoftaccount/callback //for easy auth
https://localhost:44337/signin-microsoft //manually MSA authentication for dev locally
Moreover, you could follow this issue to manually attach all claims for current user. Then you could retrieve the user claims in the same way for the manually MSA authentication and Easy Auth.
If you are using App Service Authentication (EasyAuth), according to Microsoft documentation page:
App Service passes some user information to your application by using special headers. External requests prohibit these headers and will only be present if set by App Service Authentication / Authorization. Some example headers include:
X-MS-CLIENT-PRINCIPAL-NAME
X-MS-CLIENT-PRINCIPAL-ID
X-MS-TOKEN-FACEBOOK-ACCESS-TOKEN
X-MS-TOKEN-FACEBOOK-EXPIRES-ON
Code that is written in any language or framework can get the information that it needs from these headers. For ASP.NET 4.6 apps, the ClaimsPrincipal is automatically set with the appropriate values.
So basically, if you are using ASP.NET Core 2.0, you need to set the ClaimPrincipal manually. What you need to use in order to fetch this headers and set the ClaimsPrincipal is AuthenticationHandler
public class AppServiceAuthenticationOptions : AuthenticationSchemeOptions
{
public AppServiceAuthenticationOptions()
{
}
}
internal class AppServiceAuthenticationHandler : AuthenticationHandler<AppServiceAuthenticationOptions>
{
public AppServiceAuthenticationHandler(
IOptionsMonitor<AppServiceAuthenticationOptions> options,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock) : base(options, logger, encoder, clock)
{
}
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
return Task.FromResult(FetchAuthDetailsFromHeaders());
}
private AuthenticateResult FetchAuthDetailsFromHeaders()
{
Logger.LogInformation("starting authentication handler for app service authentication");
if (Context.User == null || Context.User.Identity == null || Context.User.Identity.IsAuthenticated == false)
{
Logger.LogDebug("identity not found, attempting to fetch from the request headers");
if (Context.Request.Headers.ContainsKey("X-MS-CLIENT-PRINCIPAL-ID"))
{
var headerId = Context.Request.Headers["X-MS-CLIENT-PRINCIPAL-ID"][0];
var headerName = Context.Request.Headers["X-MS-CLIENT-PRINCIPAL-NAME"][0];
var claims = new Claim[] {
new Claim("http://schemas.microsoft.com/identity/claims/objectidentifier", headerId),
new Claim("name", headerName)
};
Logger.LogDebug($"Populating claims with id: {headerId} | name: {headerName}");
var identity = new GenericIdentity(headerName);
identity.AddClaims(claims);
var principal = new GenericPrincipal(identity, null);
var ticket = new AuthenticationTicket(principal,
new AuthenticationProperties(),
Scheme.Name);
Context.User = principal;
return AuthenticateResult.Success(ticket);
}
else
{
return AuthenticateResult.Fail("Could not found the X-MS-CLIENT-PRINCIPAL-ID key in the headers");
}
}
Logger.LogInformation("identity already set, skipping middleware");
return AuthenticateResult.NoResult();
}
}
You can then write an extension method for the middleware
public static class AppServiceAuthExtensions
{
public static AuthenticationBuilder AddAppServiceAuthentication(this AuthenticationBuilder builder, Action<AppServiceAuthenticationOptions> configureOptions)
{
return builder.AddScheme<AppServiceAuthenticationOptions, AppServiceAuthenticationHandler>("AppServiceAuth", "Azure App Service EasyAuth", configureOptions);
}
}
And add app.UseAuthentication(); in the Configure() method and put following in the ConfigureServices() method of your startup class.
services
.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = "AppServiceAuth";
options.DefaultChallengeScheme = "AppServiceAuth";
})
.AddAppServiceAuthentication(o => { });
If you need full claims details, you can retrieve it on the AuthenticationHandler by making request to /.auth/me and use the same cookies that you've received on the request.