Multiple IdPs with Sustainsys.Saml2 for the HTTPModule and AspNetCore - multi-tenant

In a previous post (Sustainsys.SAML2 with a multitenant application) I asked about the process of adding multiple IdPs to my configuration. I have that working but need a little help on implementing this for a multitenant application.
Anders posted this response from Sustainsys:
The IdentityProviders property on the options is a collection. Just add more IdentityProvider objects to it. To select what Idp to invoke, put an item in the AuthProps with key idp and set the value to the EntityId of the Idp you want to use. It's possible to alter the collection when running.
I just need a quick code example of Anders' response of "To select what Idp to invoke, put an item in the AuthProps with key idp and set the value to the EntityId of the Idp you want to use." It seems the IdP gets put into the relaystate so when the ACS gets hit, it knows which IdP to use. Anyway, just need some help to complete my understanding of this for use in our multitenant application.

I answered my own question back in the original post. Check out:
Sustainsys.SAML2 with a multitenant application

A quick code (.NET Core using Sustainsys.Saml2) example:
var actionParams = new { authenticationType = "Saml2", returnUrl };
var properties = new AuthenticationProperties
{
RedirectUri = _linkGenerator.GetUriByAction(HttpContext, "LoginExternalCallback", null, actionParams)
};
properties.Items.Add("idp", new EntityId("someID").Id); // <--- **That's the important line**
return Challenge(properties, "Saml2"); // <--- Return Challenge from the controller

Related

new RoleManager<IdentityRole> error missing arguments in VS 2015

I want to implement User and Role Manager in VS 2015 using the Identity.EntityFramework": "3.0.0-rc1-final".
Among others I have created a class IdentityManager.
My main problem is creating a method to check the existence of a Role as follows.
public bool RoleExists(string name)
{
var RoleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(new ApplicationDbContext()));
return RoleManager.RoleExists(name);
}
I keep getting the error on new RoleManager<IdentityRole>:
There is no argument given that corresponds to roleValidators, keyNormalizer, errors, logger,contextAccessor"
Yes, basically all the parameters I am not specifying but I have no idea how to approach these.
I am very new at this and have been searching and trying for days now, if someone can just point me in the right direction I am willing to do the legwork and testing, I just need some documentation.
I am having a similar issue - it looks like the roles are not the best option in identity 3.0
This thread (ASP .NET 5 MVC 6 Identity 3 Roles Claims Groups) helped me get something working, but its sad that this is not better documented.
Here are my attempts at improving that. Asp.net.Identity (3.0.0.0-rc1-final)
in Startup.cs --> ConfigurationServices
//Define your policies here, they are strings associated with claims types, that have claim strings...
//they need to be in AspNetUserClaims table, user id, department, Dev to be allowed access to the Dev policy
//add the auth option, below that makes it work, and in the api controller, add the
//[Authorize("Dev")] attribute
//services.AddAuthorization(
// options =>
// {
// options.AddPolicy("Dev", policy => { policy.RequireClaim("department", "Dev"); });
// });

Parse JS SDK: How to set a default User ACL?

Conveniently this is blank in the JS Docs
Does an ACL have to be explicitly applied when each User is created?
I had the same question. The following appears to work, applied right after new User is created (before calling the signUp method):
var user = new Parse.User();
user.set( userObj )
var acl = new Parse.ACL();
// apply desired ACL methods here..
// by default, public read/write will be restricted
user.setACL( acl );
user.signUp( null, ... )
Initially, I tried passing user into new Parse.ACL() per Parse's docs, but that was not working.
(I'm now reading up on the Cloud Code because perhaps such security logic be better done there?)

Security: Session Identifier Not Updated in tcl

I'm working on open-source application "Project-Open" and during the scanning I got the following vulnerability:
[Medium] Session Identifier Not Updated
Issue: 13800882
Severity: Medium
URL: https://<server_name>/register/
Risk(s): It is possible to steal or manipulate customer session and cookies, which might be used to impersonate a legitimate user,allowing the hacker to view or alter user records, and to perform transactions as that user
Fix: Do not accept externally created session identifiers
though the fix is mentioned but it is not sufficient for me to understand it completely.please guide me how should I remove this.Also let me know if any further details are needed to understand the question.
The project source code is in tcl
I found the following code which does the same but it's in java.
public HttpSession changeSessionIdentifier(HttpServletRequest request) throws AuthenticationException {
// get the current session
HttpSession oldSession = request.getSession();
// make a copy of the session content
Map<String,Object> temp = new ConcurrentHashMap<String,Object>();
Enumeration e = oldSession.getAttributeNames();
while (e != null && e.hasMoreElements()) {
String name = (String) e.nextElement();
Object value = oldSession.getAttribute(name);
temp.put(name, value);
}
// kill the old session and create a new one
oldSession.invalidate();
HttpSession newSession = request.getSession();
User user = ESAPI.authenticator().getCurrentUser();
user.addSession( newSession );
user.removeSession( oldSession );
// copy back the session content
for (Map.Entry<String, Object> stringObjectEntry : temp.entrySet()){
newSession.setAttribute(stringObjectEntry.getKey(), stringObjectEntry.getValue());
}
return newSession;
}
P.S. I'm newbie in TCL.
please let me know if you need any further explanation.
There is a fix in OpenACS 5.9 that addresses your scanning reports. Please see the following discussion on OpenACS.org for reference.
http://www.openacs.org/forums/message-view?message_id=5332821
The problem that the OWASP report is talking about is the inability to migrate a session to use a new ID, making it easier for an attacker to discover the ID and reuse it. The protection against this is to change the session ID from time to time (no, I don't know how often!) and that Java code is involved in doing just that.
A session is represented as a token stored in the browser, usually in a cookie (and this is what cookies are designed to do). That token is then used to look up the database record corresponding to the session, which holds serializations of the key/value mappings in the session. It's a simple mechanism, but very powerful. The Java code for doing all this will be fairly complex behind the scenes because of the serialization, etc., but Tcl values are (usually, and always for built-in types) naturally serializable and so should prove much less of a problem in this; copying a session to a new key could be done without having to deserialize in the first place.
The exact code for doing this depends on the framework in use. I don't know what ]project-open[ uses, so that's as far as we can drill right now. You need to talk to other people actually working on PO…
For all that, the best way would be to make the key given to clients not be the primary key, so that you can change the session key without having to delete things. Just have a session key column (with an index!) and you'll be able to make things work fine. This is a more sophisticated approach though; it might not be practical to implement in your environment..

How can I make the [Authorize] attribute more flexible?

I have an MVC 5 application that I lock down by only allowing certain authenticated users to have access to specific actions within my controller. I utilize the authorize attribute at the top of the class allowing only the user(s) I want to gain access after login. I do this with the following attribute placed at top of my class...
[Authorize(Users="user1,user2")]
This works great! However, what if I don't want to recompile and deploy the application everytime I want to add a new user to this specific controller?
I thought I might add this in my web.config file under as a key like so...
<appSettings>
<add users="user1,user2"/>
</appSettings>
But when I try to access this key in my controller like so: [Authorize(Users=ConfigurationManager.AppSettings["users"])] I am getting an error: Cannot resolve symbol 'AppSettings'.
Is there a way to do this?
I'm not sure why an answer that didn't answer the question was accepted. Regardless, I thought it might be worth adding an answer for any future travelers.
While this functionality isn't provided out of the box, it's certainly possible by writing your own authorize attribute.
public class ConfigAuthorize : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var allowedUsers = ConfigurationManager.AppSettings["CoolActionAllowedUsers"];
var allowedUsersArray = allowedUsers.Split(',');
if (httpContext.User.Identity != null && allowedUsersArray.Contains(httpContext.User.Identity.Name))
{
return true;
}
return false;
}
}
And to use the attribute:
[ConfigAuthorize]
public ActionResult CoolAction() {
//...
}
In the code above when your authorization is performed in AuthorizeCore, the configuration value from CoolActionAllowedUsers will be pulled into memory and the currently authenticated user will be verified if they are in the list of allowed users. If you make a change to your config file it won't be a problem; the application pool will automatically restart and the next time the code runs to read the config file your new value will be read.
I completely agree with #Shoe that roles should be used. Managing a list of users in your code is just a pain in the arse. In fact, at work, anytime I get a request for just one random user to have access to a page I always require a group to be setup. However the code above could apply to a list of roles as well.
Instead of using the Users parameter use the Roles parameter.
[Authorize(Roles="CanExecuteActions")]
Now you can manage what users have access to your controller by giving them this role. Any user without the role can't execute any actions of the controller.

Grails / Spring rememberMe handling of multiple browsers for same user + session concurrency

Using rememberme feature of grails security plugin based on Spring Security Core.
my config.groovy relevant contents are as follows:
// Added by the Spring Security Core plugin:
grails.plugins.springsecurity.userLookup.userDomainClassName = 'org.blah.user.User'
grails.plugins.springsecurity.userLookup.authorityJoinClassName = 'org.blah.user.UserRole'
grails.plugins.springsecurity.authority.className = 'org.blah.user.Role'
grails.plugins.springsecurity.successHandler.defaultTargetUrl = '/home'
grails.plugins.springsecurity.rememberMe.persistent = true
grails.plugins.springsecurity.rememberMe.persistentToken.domainClassName = 'org.blah.user.PersistentLogin'
grails.plugins.springsecurity.rememberMe.key = 'blah'
grails.plugins.springsecurity.rememberMe.alwaysRemember = true
// set cookie expiration to one year
grails.plugins.springsecurity.rememberMe.tokenValiditySeconds = 31536000l
Got a question about what happens when same user logs in from multiple clients/browsers.
I'd like cookie to be remembered across all browsers, ie require one time login per browser, and then remember going forward...
Is that the default behavior, if not, how to make that happen?
Additionally, i'd like to enforce single concurrent login, ie log in from multiple places is allowed, but restricted to only one active session per user.
the plugin doesn't do this out of the box. At a high level you'd probably need to do the following:
1) Write your own Remember Me Authentication Filter e.g. http://www.to-string.com/2012/07/11/springsecurity-capturing-rememberme-success-event/
2) You'd then have to change your own Persistent Login token to capture some other piece of data e.g. IP address or Browser and save both of those in the persistent Login Token
3) Write your own remember Me services which extends TokenBasedRememberMeServices. You'll need to override 2 methods processAutoLoginCookie and makeTokenSignature minimally to add in your own logic for checking the format of the cookie
4) wire it all together in resources.groovy with...
userDetailsService(com.yourclass.UserDetailsService)
customRememberMeServices(com.yourclass.CustomRememberMeServices) {
userDetailsService = ref("userDetailsService")
key = "key"
}
rememberMeAuthenticationFilter(com.yourclass.CustomRememberMeAuthenticationFilter) {
rememberMeServices = ref('customRememberMeServices')
authenticationManager = ref("authenticationManager")
}
What you are looking for is per-computer authentication, regardless of browser used, and this is simply not possible to do securely using only browsers and only logging in one time.

Resources