I have a WebForms site that has been running on an internal server and authenticating users against our internal Active Directory. Due to some new features that we are implementing, this site needs to be moved to an external server and then authentication changed so that it authenticates users against our Office 365 accounts. To this end I have:
Created a new WebForms site (not using MVC)
Set up a new application in Azure.
Modified the Startup.Auth.cs as follows:
public void ConfigureAuth(IAppBuilder app)
{
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions { ClientId = "MyApplicationGUID", Authority = "https://login.windows.net/MyDomain.com" });
When I go to the default page and click Log On, it takes me to the correct Login page and the button for OpenID is shown. If I click the button, I am taken to the Microsoft Login page where I am able to enter my credentials. However, at that point, I am redirected back to my site's login page where it is still asking for a username/password.
What I would like to have happen is to set the site up so that if a user is not authenticated, they are redirected directly to the Microsoft login page and upon successful login are redirected back to the page they requested originally. Failing this, I would be satisfied with getting the default login page working so that when I click OpenID I'm not redirected back to the login page.
I don't have time to learn MVC at this point and port the whole thing over so going that route is not an option at this time.
I don't know enough about this process, so if my question doesn't make sense or if you need more information, please let me know and I'll be glad to try and find what you need to assist me in this.
Maybe I'm missing something, but I don't see why you need the custom login page or the external signin cookie. A typical Startup.Auth for OIDC/AAD looks something like this:
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = "AppGUID",
Authority = "https://login.windows.net/MyDomain.com",
// After authentication return user to the page they were trying
// to access before being redirected to the Azure AD signin page.
Notifications = new OpenIdConnectAuthenticationNotifications()
{
RedirectToIdentityProvider = (context) =>
{
string currentUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.Path;
context.ProtocolMessage.RedirectUri = currentUrl;
return Task.FromResult(0);
}
}
});
The cookie auth is just to keep from going to AAD for every single request. All the real work happens in the OpenIdConnectAuthentication.
Here's an example of WebForms, Azure AD, and OpenID Connect:
http://www.cloudidentity.com/blog/2014/07/24/protecting-an-asp-net-webforms-app-with-openid-connect-and-azure-ad/
Related
I have deployed same application as two sites[Production and Development] in IIS 8.0 with two port number. The problem is the follow:
Open the browser and login the first application[Production];
Open another browser tab and login the second application[Development];
The first application automatically logout.
Any idea of having both should be logged in and use?
My file Startup.Auth.cs:
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.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
// Configure the sign in cookie
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
SlidingExpiration = true,
CookieName="my-very-own-cookie-name",
//ExpireTimeSpan = TimeSpan.FromMinutes(2.0),
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromHours(applTime),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)),
OnResponseSignIn = context =>
{
context.Properties.AllowRefresh = true;
context.Properties.ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(idleTime);
}
}
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
I have a legacy MVC App using AD B2C for authentication. The behavior I want, is to be able to redirect users to my login page instead of the B2C login page. Once on my login page, I will do some pre-validation and then send the user a challenge. I have tested the following and the callback of this challenge works and returns Identity/Claims of a user (per example http://bitoftech.net/2016/08/31/integrate-azure-ad-b2c-asp-net-mvc-web-app/comment-page-1/#comment-129447).
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(SignUpPolicyId));
app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(ProfilePolicyId));
app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(SignInPolicyId));
To achieve a redirect to my login page, I have referenced the following SO, which works EXCEPT I do not get Claims/Identity information in my callback. Reference to SO: CookieAuthenticationOptions.LoginPath value not used when also using app.UseOpenIdConnectAuthentication
Here is my code changes:
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(SignUpPolicyId));
app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(ProfilePolicyId));
app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(SignInPolicyId));
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "ApplicationCookie",
LoginPath = new PathString("/Account/Login")
});
How do I get my claims/identity in my call back? Request.IsAuthenticated is also false. My callback:
[AllowAnonymous]
[HttpGet]
public ActionResult Callback() {
var identity = (ClaimsIdentity)User.Identity;
IEnumerable<Claim> claims = identity.Claims;
//CLAIMS ONLY HAS NAME AND IS EMPTY - THERE SHOULD BE 18 CLAIMS
return RedirectToAction("Index", "AppIndex");
}
From my understanding of what you are trying to achieve, this is not currently possible.
Please refer to the FAQ for Azure B2C:
Can I use my own URLs on my sign-up and sign-in pages that are served by Azure AD B2C? For instance, can I change the URL from
login.microsoftonline.com to login.contoso.com?
Not currently. This feature is on our roadmap. Verifying your domain
in the Domains tab in the Azure portal does not accomplish this goal.
You can, however, upvote the feature request and subscribe to Azure User Voice to be notified when this feature is available.
I have created two MVC applications that share the same authentication. In the applications I'm using different user roles that can be assigned to every user. When I log in as an administrator, everything works fine, I log in to the first application and the same cookie is used to log in to the second application, no login prompts involved.
When I log in as a user with a different role assigned to them, the login screen pops up again after logging in to the first application and it doesn't go away, even if I log in there also.
The applications are both on the same IIS server. The machine key is configured correctly in IIS server (obviously, since it works if I log in as a user with the administrator role assigned) and here is the code in Startup.Auth.cs for both applications:
1st Application:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
CookieName = "DefaultCookie",
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
2nd Application:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
CookieName = "DefaultCookie",
AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("./Account/Login"),
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)),
OnApplyRedirect = ApplyRedirect
},
});
private static void ApplyRedirect(CookieApplyRedirectContext context)
{
Uri absoluteUri;
if (Uri.TryCreate(context.RedirectUri, UriKind.Absolute, out absoluteUri))
{
var path = PathString.FromUriComponent(absoluteUri);
Trace.WriteLine(path);
if (path == context.OwinContext.Request.PathBase + context.Options.LoginPath)
context.RedirectUri = "/Account/Login" +
new QueryString(
context.Options.ReturnUrlParameter,
context.Request.Uri.AbsoluteUri);
}
context.Response.Redirect(context.RedirectUri);
}
Does anyone know why this is happening and what I can do to fix it?
This is an authorization issue, not an authentication issue. If you can share the login at all, i.e. in the case of your admin user, then everything is fine on that front. However, the user's role must be authorized to access the controller/action or they will still be redirected to the login page, even though they are already authenticated. This is intended as an opportunity for them to re-authenticate with an account with the appropriate privileges, since the one they used apparently does not have access.
Long an short, you need to ensure that whatever controller(s)/action(s) you want the user to be able to access allow the role that is assigned to them.
In my application I want to log the user off after a period of inactivity. Users log in using their Google account.
In the Web.config file, I put <sessionState mode="InProc" timeout="10" /> under <system.web>, however after 10 mins, the user was not logged off.
Another thing I would like the auto log off to do is to execute a piece of code before completing the log off. This code simply updates a field in a database table. I don't want to use JavaScript because I want the auto log off to work if the user navigates away from the website.
EDIT
Code inside Startup.Auth.cs as requested by #Igor
using System;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.Google;
using Owin;
using StudentLive.Models;
namespace StudentLive
{
public partial class Startup
{
// For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.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
// Configure the sign in cookie
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process.
app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
// Enables the application to remember the second login verification factor such as phone or email.
// Once you check this option, your second step of verification during the login process will be remembered on the device where you logged in from.
// This is similar to the RememberMe option when you log in.
app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
// Uncomment the following lines to enable logging in with third party login providers
//app.UseMicrosoftAccountAuthentication(
// clientId: "",
// clientSecret: "");
//app.UseTwitterAuthentication(
// consumerKey: "",
// consumerSecret: "");
//app.UseFacebookAuthentication(
// appId: "",
// appSecret: "");
app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
{
ClientId = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX",
ClientSecret = "XXXXXXXXXXXXXXXXXXXX"
});
}
}
}
You need to modify the CookieAuthenticationOptions instance and provide additional details for your expiration.
From the documentation
SlidingExpiration - The SlidingExpiration is set to true to instruct the middleware to re-issue a new cookie with a new expiration time any time it processes a request which is more than halfway through the expiration window.
ExpireTimeSpan - Controls how much time the cookie will remain valid from the point it is created. The expiration information is in the protected cookie ticket. Because of that an expired cookie will be ignored even if it is passed to the server after the browser should have purged it.
Code:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
// add these lines
SlidingExpiration = true,
ExpireTimeSpan = TimeSpan.FromMinutes(10),
// rest of your code
}
ExternalLoginInfo loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
Why must this line always return null? It happens when the user tries to login using ANY provider. I know the FLOW is correct because actually it works locally, but when I deploy the website it always returns null.
From what I understand it's using an external cookie to track this and I can be sure it's not the browser because it works locally on the same browser.
This happens for ALL providers, even though I've double checked that all of them have the domain as "allowed" in each respective control panel. Like I said everything works locally.
I've tried restarting IIS as some answers suggested.
Also have these lines in Startup.Auth.cs with the cookie domian correctly set
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
CookieDomain = ".example.com",
...
});
//use a cookie to temporarily store information about a user logging in with a third party login provider
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
Make sure your (facebook, twitter etc.) provider settings are not overriden on deployment.
Also make sure that your callback url is correctly registered at the provider. I'm using LinkedIn which needs a full url to your callback, eg. https://domain.com/signin-linkedin
I have the following setup, which works without any problems:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
CookieSecure = CookieSecureOption.SameAsRequest,
CookieName = "CustomCookieName",
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, User>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => Some.Custom.Identity.Helper.GenerateUserIdentityHelperAsync(user, manager)) // This helper method returns ClaimsIdentity for the user
}
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);