implement Microsoft Authentication (owin) on an existing WebForms web app - asp.net-mvc

I'm trying to implement Microsoft Authentication (owin) on an existing WebForms web application. I can't use the official guides from Microsoft, since they are made for modern solutions with MVC.
Any tips on where to start? I can't find any guides.

Please follow the document which helps you in old .NET forms to use OWIN Forms middleware and to use this middleware for Azure AD authentication please follow Docs.

Install the package for Microsoft.Owin.Security.Cookies
Right click the App_Start folder on your project Add -> New Item - > "OWIN Startup Class"
then create the following folder
public void Configuration(IAppBuilder app)
{
CookieAuthenticationOptions opt = new CookieAuthenticationOptions();
opt.AuthenticationType = CookieAuthenticationDefaults.AuthenticationType;// "Identity.Application";
opt.CookieName = ".SSO";
opt.CookieDomain = "localhost";
opt.SlidingExpiration = true;
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("192.168.1.96:6379");
IDataProtector proc = DataProtectionProvider.Create(new DirectoryInfo(#"C:\test\core"), buildAction =>
buildAction.SetApplicationName("MyApp").SetDefaultKeyLifetime(TimeSpan.FromDays(9000)).ProtectKeysWithDpapi().PersistKeysToStackExchangeRedis(redis)).CreateProtector("Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware", "Cookies", "v2");
DataProtectorShim shim = new DataProtectorShim(proc);
opt.TicketDataFormat = new AspNetTicketDataFormat(shim);
app.UseCookieAuthentication(opt);
}

Related

ServiceStack Admin UI

I'm trying to integrate the /admin-ui functionality in my application, that uses the ServiceStack's built-in ApiKeyAuthProvider, for give the user the possibility to register other users.
In the login page that this functionality renders, when I write my apikey and press the sign in button, through the developer tool console, I see the error "!AuthProvider", that sounds like that the app cannot recoignize the ApiKeyAuthProvider.
This is my AppHost Configure method:
public override void Configure(Container container)
{
//Create and register an OrmLite DB Factory configured to use Live DB by default
var dbFactory = new OrmLiteConnectionFactory(
AppSettings.Get<string>("connString"), SqlServerDialect.Provider);
container.Register<IDbConnectionFactory>(dbFactory);
//Tell ServiceStack you want to persist User Auth Info in SQL Server
container.Register<IAuthRepository>(c => new OrmLiteAuthRepository(c.Resolve<IDbConnectionFactory>()));
container.Resolve<IAuthRepository>().InitSchema();
//Register the AuthFeature with the API Key Auth Provider
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[] {
new ApiKeyAuthProvider(AppSettings)
}));
Plugins.Add(new AdminUsersFeature());
}
Could someone help me please? (ServiceStack v.6.0.2)
Thanks in advance
EDIT:
This issue should be resolved from the latest v6.0.3 pre-release that's now available on MyGet.
If you have an existing ServiceStack v6.0.3 installed you'll need to clear your NuGet packages cache to update to the latest version, e.g:
$ nuget locals all -clear

DataProtectionBuilder.ProtectKeysWithAzureKeyVault not working in .net 4.7.2

ProtectKeysWithAzureKeyVault is not pulling key from Azure KeyVault using .net 4.7.2.. But it works well in .netcore 2.2
I do the following:
public void ConfigureAuth(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Identity.Application",
CookieName = ".AspNet.SharedCookie",
LoginPath = new PathString("/Account/Login"),
TicketDataFormat = new AspNetTicketDataFormat(
new DataProtectorShim(
DataProtectionProvider.Create(new DirectoryInfo(#"E:\SBH"), (builder) => {
builder
.ProtectKeysWithAzureKeyVault(
"https://test.vault.azure.net/keys/jwt",
"ClientID",
"ClientScret")
.PersistKeysToFileSystem(new DirectoryInfo(#"E:\SBH"));
}).CreateProtector(
"Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware",
"Identity.Application",
"v2"))),
CookieManager = new ChunkingCookieManager()
});
}
The code runs without any errors / exceptions. But not making call to azure key vault.
What is the Problem?
I have installed these two nuget packages
Microsoft.Owin.Security.Interop
Microsoft.AspNetCore.DataProtection.AzureKeyVault
As the article said, the AzureDataProtectionBuilderExtensions.ProtectKeysWithAzureKeyVault Method only apply to asp.net core 2.1 and 2.2. So it will not working in .net4.7.2.
I could solve the issue by using AspNetCore with framework pointing to .NetFramework while creating the solution.
With this arrangement, I could use the .AspNetCore functions along with .Net 4.7.2 assemblies for the backward compatibility.
And Used the Regular .NetCore middleware functions for dataprotection like below
services.AddDataProtection()
.PersistKeysToAzureBlobStorage(container, blobName)
.ProtectKeysWithAzureKeyVault("KeyUri","ClientId", "ClientSecret")
.SetApplicationName("Name");

ADFS with existing ASP.Net MVC App

I've been looking around, trying to find an example of how to add ADFS authentication to an existing ASP.Net MVC application. I found lots of example of how to do it using the wizard when you create a new app.
I could create a new app and copy the code and config over, but this seams like a strange approach.
Does anyone know of a good guide or resource?
We found this blog entry on Cloud Identity to be really helpful to get started with something similar. We are using Web API so it's not exactly the same.
You will need to add this to your Startup.Auth.cs file:
app.UseActiveDirectoryFederationServicesBearerAuthentication(
new ActiveDirectoryFederationServicesBearerAuthenticationOptions
{
Audience = ConfigurationManager.AppSettings["ida:Audience"],
MetadataEndpoint = ConfigurationManager.AppSettings["ida:MetadataEndpoint"]
});
In your web.config you will need keys to point to those entries:
<add key="ida:AdfsMetadataEndpoint" value="https://adfs.yourdomain.com/federationmetadata/2007-06/federationmetadata.xml" />
<add key="ida:Audience" value="https://yourmvc.yourdomain.com" />
Note that what version of ADFS you are using makes a big difference. We found that while trying to get tokens to work with version 3.0 of ADFS they are somewhat broken at the moment. On premises ADFS will also work much differently than Azure.
We needed to customize the claims for our implementation and this post helped immensely. Startup.Auth.cs will look similar to this:
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Audience = ConfigurationManager.AppSettings["ida:Audience"],
Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
Provider = new OAuthBearerAuthenticationProvider()
{
OnValidateIdentity = async context =>
{
context.Ticket.Identity.AddClaim(
new Claim(http://mycustomclaims/hairlenght,
RetrieveHairLenght(userID),
ClaimValueTypes.Double,
"LOCAL AUTHORITY");));
}
}
});

Get Error (error=access_denied) while logging in MVC5 application with facebook SDK

I have developed an application with ASP.NET MVC5. I have used Facebook external authentication in my application.
When I debug this application with the "Locallhost" domain, the Facebook login works well but when I publish the application in the main server,the AuthenticationManager.GetExternalLoginInfo() returns null and it gives me an error like this in the url:
http://xxxxx.com/Account/ExternalLoginCallback?ReturnUrl=%2Fen&error=access_denied#_=_
I have set the "Site URL" as "http://xxxx.com" and "Valid OAuth redirect URIs" as "http://xxxx.com/signin-facebook" in the Facebook development console.
My setting in the Startup.Outh.cs file is:
var FacebookOptions = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationOptions();
FacebookOptions.AppId = ConfigurationManager.AppSettings["Facebook_User_Key"];
FacebookOptions.AppSecret = ConfigurationManager.AppSettings["Facebook_Secret_Key"];
FacebookOptions.Provider = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationProvider()
{
OnAuthenticated = async context =>
{
context.Identity.AddClaim(new System.Security.Claims.Claim("FacebookAccessToken", context.AccessToken));
foreach (var claim in context.User)
{
var claimType = string.Format("urn:facebook:{0}", claim.Key);
string claimValue = claim.Value.ToString();
if (!context.Identity.HasClaim(claimType, claimValue))
context.Identity.AddClaim(new System.Security.Claims.Claim(claimType, claimValue, "XmlSchemaString", "Facebook"));
}
}
};
FacebookOptions.SignInAsAuthenticationType = DefaultAuthenticationTypes.ExternalCookie;
app.UseFacebookAuthentication(FacebookOptions);
I don't know why the external login does not work only in the server with my main domain name. please help me about this problem.
I encountered pretty much the same symptoms you describe:
shortly:
A Facebook authentication worked well on localhost, and after uploading the project to another server (and changing the site URL on Facebook console), authentication did not succeed.
I would recommend you roll back to the MVC template code, and if that works - notice any changes you have made to the middleware code (Startup.Auth.sc).
In particular pay attention to code that interacts with LOCAL configuration, such as Disk I/O and OS permissions for local services.
My particular case:
Starting from the Owin/Katana supported Visual Studio template of a WebAPI project, external login was working perfectly with Facebook, Microsoft and Google OAuth middleware, when testing on localhost.
Later I added come code to Startup.Auth.sc because I needed further authentication activity.
So this was the original code:
public void ConfigureAuth(IAppBuilder app)
{
// see WebAPI template of Visual Studio 2013/2015
...
app.UseFacebookAuthentication(
appId: 99999999,
appSecret: *******);
}
and this was replacement:
public void ConfigureAuth(IAppBuilder app)
{
// see WebAPI template of Visual Studio 2013/2015
...
app.UseFacebookAuthentication(GetFacebookAuth());
}
private FacebookAuthenticationOptions GetFacebookAuth()
{
string picRequest =
String.Format("/me/picture?redirect=false&width={0}&height={0}", ProfileInfoClaimsModel.PIC_SIDE_PX);
var facebookProvider = new FacebookAuthenticationProvider()
{
OnAuthenticated = async (context) =>
{
var client = new FacebookClient(context.AccessToken);
dynamic me = client.Get("/me?fields=id,name,locale");
dynamic mePicture = client.Get(picRequest);
// storing temporary social profile info TO A LOCAL FOLDER
// uploading the local folder to a service WITH A LOCAL CREDENTIAL FILE
...
}
};
var options = new FacebookAuthenticationOptions()
{
AppId = 0123456789,
AppSecret = ******,
Provider = facebookProvider,
};
return options;
}
You may notice that my comments will make the problem obvious - the code points to local resources.
Then I published the project to a virtual server (by Amazon EC2) running Windows Server 2012 with IIS 8.5.
From that moment I kept getting error=access_denied in the redirect from /signin-facebook.
I decided to follow this good old concept, and go back to the original template code. Pretty soon I figured out that I forgot to configure the new server. For instance, the folder the code refers to did not exist and the site had no permission to create it.
Obviously, that solved it.

Project subdirectory as root for static files

New to ASP.NET MVC, I am creating a web application using the Visual Studio 2013 wizard. It creates several folders from where static files are served: Content, Scripts, etc.
Frameworks in other languages (e.g. TurboGears) have an explicit directory only for static content, removing the risk of serving the source code of a page instead of processing it which is a typical configuration mistake of PHP sites.
ASP.NET however is happy to deliver anything in the application's root directory, e.g. http://localhost:1740/Project_Readme.html as long as it has the right extension. Only the Views folder is protected with a Web.config.
How do I configure the application to use another directory than the project's root directory for static files. E.g. if the file favicon.ico is put into the subdirectory Content, it should be accessible as http://localhost:1740/favicon.ico, but nothing outside of the Content directory unless returned by a controller.
Nothing should ever be executed in this directory, that is, if *.cshtml files are put into this directory, the files' contents (the source code) should be delivered as text/plain.
Final application will run using mod_mono on Linux.
Update:
Ben,
The proposed solution works only with Owin. To get it working in an MVC application you have to use asp.net MVC 6 (part of asp.net core or asp.net 5) only. But, with Web API you can use the older versions too. To setup the application please use the following steps:
Create an empty project using visual studio templates(don't select Web API or MVC)
Add the following Nuget packages to the project:
Microsoft.AspNet.WebApi
Microsoft.AspNet.WebApi.Owin
Microsoft.Owin.Host.SystemWeb
Microsoft.Owin.StaticFiles
Add a Startup.cs file and decorate the namespace with the following
[assembly: OwinStartup(typeof(Startup))]
Add the following code to the Stratup.cs class
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new {id = RouteParameter.Optional}
);
//Configure the file/ static file serving middleware
var physicalFileSystem = new PhysicalFileSystem(#".\client");
var fileServerOptions = new FileServerOptions
{
EnableDefaultFiles = true,
RequestPath = PathString.Empty,
FileSystem = physicalFileSystem
};
fileServerOptions.DefaultFilesOptions.DefaultFileNames = new[] {"index.html"};
fileServerOptions.StaticFileOptions.ServeUnknownFileTypes = true;
fileServerOptions.StaticFileOptions.FileSystem = physicalFileSystem;
app.UseFileServer(fileServerOptions);
app.UseWebApi(config);
}
This should do the magic. Now you can host the application in IIS. IIS will serve the static assets only from client folder. Add Server folder and add controllers.
The Microsoft.Owin.Host.SystemWeb is what facilitates the hosting of Owin application in IIS. The file serve options help IIS to serve static files only from client folder.
Please let me know if you have any questions.
Based on your question, the project structure that you want to achieve should be like the following.
Basically you will have two folders only, Client and Server. Static files are served from client folder only. Server folder is not accessible. If this is what you need then it can be achieved easily with Owin Self Host with Static File Serving middleware.
Self host works with out any dependency on IIS. But, if your planning to host this application on Linux, you could use Asp.NET CORE 1.0. Later if you decide to host the application on IIS inside windows that can be achieved easily by adding the Microsot.Owin.Host.SystemWeb nuget package.
There are great blog posts on this topic. This is the link for one of them. Here is the link for achieving the same in Asp.NET Core.
I hope this solves your issues and please let me know if you have any questions.
Thank you,
Soma.
The best solution I found is to ignore asp.net normal way and write a new way
public override void Init()
{
BeginRequest -= OnBeginRequest;
BeginRequest += OnBeginRequest;
}
protected void OnBeginRequest(object sender, EventArgs e)
{
if (Request.Url.AbsolutePath.StartsWith("/endPoint"))
{
Context.RemapHandler(endPoint);
}
else
{
Context.RemapHandler(staticHandler);
}
}
Let endPoint and staticHandler implement IHttpHandler
it works but every static file moves through c# so there might be a solution with better performance

Resources