I am front-ending an app with Shibboleth authentication. How can I retrieve the authenticated username in order to display it in my app?
You need to have that attribute released to you. Typically it will be added as a header to the request by the local SP, at least that's the way it works on IIS with the ISAPI extension.
You can access the Attributes in a manner specific to your application's language and environment. The preferred method is to use environment variables, but you can also use HTTP request headers, which can have some security issues because clients can "fake" whatever headers they want (however, some HTTP front-ends like nginx will drop headers that have underscores in them, which is what the Shibboleth Native SP would typically use).
If you're using Java on Tomcat, for example, you would have mod_proxy_ajp on Apache HTTP working with mod_shib2, and you would configure the SP to prepend "AJP_" to the header/variables so that the mod_proxy_ajp code puts those on the Request as Attributes instead of Headers.
Anyway, once you know that the username (possibly the Principal/Subject) is being passed to your application, you can simply access it via the typical Attribute access methods for your programming language as noted in the link above.
eduPerson Object Class Specification (200806)
2.2.8. eduPersonPrincipalName (defined in eduPerson 1.0); OID: 1.3.6.1.4.1.5923.1.1.1.6
RFC 4512 definition
( 1.3.6.1.4.1.5923.1.1.1.6
NAME 'eduPersonPrincipalName'
DESC 'eduPerson per Internet2 and EDUCAUSE'
EQUALITY caseIgnoreMatch
SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )
Application utility class: standard; # of values: single
Definition
The "NetID" of the person for the purposes of inter-institutional authentication. It should be represented in the form "user#scope" where scope defines a local security domain. Multiple "#" signs are not recommended, but in any case, the first occurrence of the "#" sign starting from the left is to be taken as the delimiter between components. Thus, user identifier is to the left, security domain to the right of the first "#". This parsing rule conforms to the POSIX "greedy" disambiguation method in regular expression processing. When the scope is a registered domain name, the corresponding registrant organization is to be taken as the scope. For example, francis#trinity.edu would imply that the identity behind the ePPN has the "NetID" "francis" at the instituion of higher education that registered itself with the domain name "trinity.edu." If other value styles are used, their semantics will have to be profiled by the parties involved. Each value of scope defines a namespace within which the assigned principal names are unique. Given this rule, no pair of eduPersonPrincipalName values should clash. If they are the same, they refer to the same principal within the same administrative domain.
Notes
If populated, the user should be able to authenticate with this identifier, using locally operated services. Local authentication systems should be able to adequately affirm (to both local and remote applications) that the authenticated principal is the person to whom this identifier was issued.
The initial intent is to use this attribute within the Shibboleth project, http://shibboleth.internet2.edu/. However, it has quickly become clear that a number of other applications could also make good use of this attribute (e.g. H.323 video, chat software, etc). eduPersonPrincipalName (EPPN) would be used as follows: A resource owner, A, would look at B's directory entry to discover B's EPPN. A would then tell the local authorization system that B's EPPN is allowed to use the resource. When B tries to access the resource, the application (or access control infrastructure) would validate B's identity, check with the local authorization system to ensure that B has been granted the appropriate access privileges, and then either grant or deny access.
EPPN looks like a Kerberos identifier (principal#realm). A site might choose to locally implement EPPN as Kerberos principals. However, this is not a requirement. A site can choose to do authentication in any way that is locally acceptable.
Likewise, EPPN should NOT be confused with the user's published email address, although the two values may be the same. Some sites have chosen to make the user portion of email addresses and security principals the same character string; other sites have chosen not to do this. Even when they appear to be the same, they are used in different subsystems and for different purposes, and there is no requirement that they have to remain the same.
The uid attribute of the user's object within the local white pages directory may also contain a login id, a security principal; some systems (eg NDS) may put a login id in the cn attribute. These attributes are defined within objectclasses that are universal. Unfortunately, their use is not prescribed in a sufficiently precise and consistent manner for use with cross domain authorization. A variety of systems already make conflicting use of these attributes; consequently, we have defined this new attribute.
An assumption is that EPPNs are managed on an enterprise basis by the univ of univ.edu. A particular EPPN is assigned solely to the associated user; it is not a security principal identifier shared by more than one person. Lastly, each EPPN is unique within the local security domain.
How long, if ever, before a formerly assigned EPPN is reassigned to a differrent individual is an institutional decision. Some institutions will choose never to reassign EPPNs. Others may opt for a relatively short hiatus before reassignment. While this complicates the work of the relying parties, it is unavoidable given institutional autonomy. See MACE best practice documents on identifiers for further discussion of these issues.
This attribute should prove useful in creating some applications that are based on currently deployed technologies and on code that does not currently use LDAP or require a PKI. This attribute should help to create a framework to foster interesting inter-institutional collaborations between sites that use different technologies. In short, this attribute provides a foundation for yet another abstraction layer.
Example applications for which this attribute would be useful
controlling access to resources
Example (LDIF Fragment)
eduPersonPrincipalName: hputter#hsww.wiz
Syntax: directoryString; Indexing: pres,eq,sub
References:
http://middleware.internet2.edu/eduperson/docs/internet2-mace-dir-eduperson-200806.html#eduPersonPrincipalName
Related
I've been developing an application that uses SSPI for Client / Server authentication. Everything works fine, but still one question remains.
The first argument of SspiPromptForCredentials is the target name... But what is it really used for?
I can literally put anything as a target name, my code will work. I don't even see it written anywhere (in the GUI).
Is it related to the authentication method? I use Negotiate.
Thanks for your help :)
I think it might be related to how the credentials are saved in the credential manager.
The only SspiPromptForCredentials example I can find on MSDN just uses a simple useless string ("Target").
For CredUIConfirmCredentials MSDN says:
Pointer to a null-terminated string that contains the name of the target for the credentials, typically a domain or server application name.
This must be the same value passed as pszTargetName to CredUIPromptForCredentials or CredUICmdLinePromptForCredentials
CredUICmdLinePromptForCredentials has a similar parameter and for this MSDN says:
A pointer to a null-terminated string that contains the name of the target for the credentials, typically a server name.
The pszTargetName parameter is used to identify the target information and is used to store and retrieve the credential.
...
Credentials are stored in the credential manager based on target name. Each target name is stored as generally as possible without colliding with credentials already stored in the credential manager. An important effect of storing credentials by target name is that a particular user can have only one credential per target stored in the credential manager.
These other CredUI functions are perhaps lower-level but I think the parameter usage is the same.
MSDN says this about Negotiate:
To allow Negotiate to select the Kerberos security provider, the client application must provide a service principal name (SPN), a user principal name (UPN), or a NetBIOS account name as the target name. Otherwise, Negotiate always selects the NTLM security provider.
The answer is a little more benign than you might think. SSPI supports arbitrary credential types, so the API needs to provide a way to prompt for credentials that a particular SSP understands without having to expose a 3rd party API. You can't launch a UI from within the SSP itself because it runs in LSA, so there's an implicit contract between the app builder and the SSP builder that if you need special credentials you're going to have to call SspiPromptForCredentials.
In some cases it's possible that SSP you're trying to use might require knowledge of the target to form the shape of the marshaled credential. Often times it doesn't.
Negotiate just happens to not require that information because the credentials you enter are not dependent on the target.
Description
Assigning users to a partial list of resource entities to limit access (or visibility) is pretty common (e.g. assigning devices to a user).
Currently we have implemented authorization at the REST API level based on resource (/devices) along with http verbs (GET, POST, etc.) to control read, write access. But, this only allows users to manage either all devices or nothing.
Solution #1
device-service itself maintains user-device associations, and does filtering based on the userId extracted from the auth token on the fly.
Cons: This will introduce dependency between device and account services. Also, we will have to repeat this implemenation for other types of entities in their own services.
Solution #2
Implement user-device associations at the API Gateway level. This way, services simply need to provide filtering by userId which becomes optional to them. There is also no need to extract userId from the auth token.
Cons: This solution burdens the API gateway with association checking.
Is there a better or standard approach to dealing with this kind of resource entity level access control in microservices?
I want to provide access to address books and calendars that may have search filters (e.g. tags, user, groups) applied.
They should not be auto-discoverable because there may be billions of combinations but must nonetheless be compatible with common clients (e.g. iOS / OS X, Windows Phones), i.e. it should be possible to add the URL with filters to the client.
One issue seems to be that some clients rely on discovery features rather than the URL you give them, e.g. iOS (you try to add one address book by exact URL and it adds all discoverable ones instead).
Another thing is structuring the optional filters.
What about using paths?
What is considered best practice here?
Are the calendars readonly or readwrite? If they are readonly, you can use webcal URLs for calendars (aka 'subscribed calendar' or iCalendar-over-HTTP).
For Cal/CardDAV calendars the Apple devices (and most other DAV clients) configure a full account (using the regular account discovery mechanisms), not just 'a URL'. I don't think there is a way around this.
Assuming you are building a web service which provides a registry/search-engine or which is an aggregator of such calendar or address data, this service could then provide Cal/CardDAV accounts (which implements the discovery).
On your web-service you would then have two options:
proxy (and potentially cache) the remote data
create a 'CalDAV subscribed calendar' (a special WebDAV resource which points to a CalDAV calendar (resource type {http://calendarserver.org/ns/}subscribed)).
For contacts you only have choice 1. And as an extra complication you might want to expose the stored queries as vCard groups instead of CardDAV collections. This is because some clients (i.e. some MacOS Contacts apps) only support one CardDAV collection (and only use groups to structure the data).
Sample: Lets say you invented a service called 'Caloogle.com'. The user needs to get some account on that service (could be auto-created, etc). The user adds a CalDAV account to his iOS device (e.g. using a preconfigured profile, so that he doesn't have to enter all the data), which then connects to Caloogle to fetch data into the iOS EventKit database.
Now in your Caloogle app (or on the website), you let the user search for calendar data. If the user found a set he likes, he saves that as a calendar into Caloogle, say 'Dividend Release Dates BP, Apple and AlwaysRightInstitute'. iOS will ping the account eventually and pick up the saved calendar. User is amazed and happy.
How you actually implement the web service (proxy or name-to-url map) depends a lot on where your data is coming from ...
Makes sense?
P.S.: Be careful when storing queries in URLs, some HTTP infrastructure components have limits on the length of a URL, and advanced queries can quickly overflow this.
Like hnh said in his answer, smart clients will try to discover the DAV services you are offering when you configure CardDAV or CalDAV from a URL rather than just use that very URL, so there seems to be no clean way to provide multiple virtual collections filtered by tags, users, groups etc.
The simplest solution that could work is to provide one virtual DAV server for each filter URL, with full service discovery within the constraints of that filter URL.
Virtual endpoints are provided with the help of URL rewriting, a feature found in common web servers, and will all point to the same DAV server code base and supply it with the filter criteria.
If for example, you want CalDAV / CardDAV collections of items that have the tags PR and Spain, you could expose them under https://dav.server/tag:PR/tag:Spain/, while items with a tag China can be exposed under https://dav.server/tag:China/.
Note that each URL provides full DAV functionality with discoverability.
As discovery is relative to the respective roots https://dav.server/tag:PR/tag:Spain/ and https://dav.server/tag:China/, there will be no interference.
Additionally, you could expose a simple URL https://server for a well-defined set of CalDAV / CardDAV collections, e.g. a default calendar / address book or some "bookmarked" collections defined by the user in some way, e.g. "PR Spain".
The simple URL would then provide these HTTP redirects, as per RFC 5785:
https://server/.well-known/caldav => https://dav.server/default
https://server/.well-known/carddav => https://dav.server/default
iOS clients and those supporting well-known URIs could then be configured by just setting the host to server and supplying login credentials.
They would then try to connect via HTTPS, check for the well-known URIs and thus discover the DAV endpoint at https://dav.server/default.
Those without well-known URI support nor discovery would require the exact URL, e.g. https://dav.server/default/calendars/jane/main or https://dav.server/tag:China/calendars/jane/main.
Is there a best practice for using claims for right-management?
I am using the new .net 4.5 and the new claim classes.
Currently I do something like that:
new ClaimsIdentity(new List<Claim>
{
new Claim("Username", user.UserName),
new Claim("UserNumber", user.UserNumber.ToString()),
new Claim("Creation_Right", ""),
new Claim("Edit_Right", "")
}
I add the right-claims without a value.
Later I check for the presence of a right. There is no need for a value (like true/false) - if it is present, its implicit 'true'.
Is there a better way to do that?
Perhaps. It looks like what you're doing is merging authentication and authorization together, making an access policy decision at the moment of authentication.
You also have the option of separating your authorization component away from your authentication component. Claims represent a set of information about a user that can be used to make an authorization decision. That is, your autheNtication step produces a set of claims, and whenever your user tries to access something, those claims are fed to the authoriZation component which renders a decision.
This provides some flexibility in that your authorization policy can change and evolve independent of your claims issuance system. For example, you might issue a role claim that identifies someone as an administrator, and you might also issue a authentication method claim that specifies how the user logged on, using a smart card or username and password for example. This gives you power in defining your access policy, you can require just an administrator role for access to some resources, while other more sensitive resources require administrator role AND use of a strong authentication mechanism. It also means you can switch between multiple different access policies depending on context. Your online whiskey store might use an ageOver21 claim on the US, but the Canadian version of your site requires over18 or over19 claims instead. Separating your authZ from your authN allows for this kind of flexibility.
I am building a multi-tenant site with MVC3. Prior to this project I had never touched either the .NET stack or web development in general, so as you can imagine my domain knowledge is somewhat lacking.
I'm still using the default AccountController architecture, but I pretty quickly determined that I didn't want to use aspnetdb.mdf for authentication, as its design is pretty different from my requirements. I do want role-based authentication, so I ultimately wrote custom User and Role classes as code-first Entity classes and used this tutorial to set up a custom MembershipProvider and RoleProvider.
Everything works fine at the moment, but as I'm building the multi-tenancy functionality it's getting messier. Based on this example, I am using a custom extension of Controller which keeps track of which tenant is using this session, and all my controllers extend this class instead of the base Controller class.
All tenants are using the same database. Each entity has a Tenant property that identifies who it belongs to.
So, here's the problem:
Usernames do not need to be globally unique. Only the combination of username and tenant must be unique. Thus, ValidateUser needs to know the username, password, and tenant. Since my custom MembershipProvider is not a Controller, it doesn't know which tenant is using the session, and the ValidateUser method only accepts username and password so I can't pass it that information.
Furthermore, pretty much everything MembershipProvider does besides ValidateUser is already implemented in a UserRepository class, which that tutorial told me to make. I'm rather fond of the Repository pattern, and it's way more convenient than adhering to MembershipProvider's interface, but now there's a massive conflict of interest between UserRepository and MembershipProvider.
So, my question:
Do I need to use MembershipProvider, or even Membership, at all?
It seems like everything MembershipProvider does would be performed more conveniently by my repository class. At this point all I'd have to do is write a new Authorize attribute that doesn't rely on Membership, and everything should work without any MembershipProvider at all, right? If I don't drop Membership I'm forced to completely mutilate my MembershipProvider implementation to the point that it barely resembles the original interface anyway.
...Either that or Membership does a ton of things I'm unaware of and removing it is blatant stupidity. That is also a distinct possibility.
No, you don't need to use Membership, but consider for a moment exactly what Membership is. Membership does not involve your users names, or addresses, or other information. Membership is strictly related to the login account of the system. It only handles details with creating, validating, updating, or deleting the information needed to login. That's it.
Likewise, the Role system is only assigning a role name to the user.
Ultimately, Membership and Roles are just implementations of the IPrincipal interface. While FormsAuthentication is an implementation of the IIdentity interface. These work together so that you can utlize the built-in ASP.NET Authorization and Authentication system.
Membership actually does have the concept of multiple tennants. This functionality is accomplished via the "ApplicationNane" field of the aspnet_users table (also settable in the Membership class itself)
From the documentation on the Membership class:
The ApplicationName is used to identify users specific to an application. That is, the same user name can exist in the database for multiple ASP.NET applications that specify a different ApplicationName. This enables multiple applications to use the same database to store user information without running into duplicate user name conflicts. Alternatively, multiple ASP.NET applications can use the same user database by specifying the same ApplicationName. The ApplicationName can be set programmatically or declaratively in the configuration for the Web application.
Now, this is designed to typically be set in the Web.Config and stay the same for the life of the app, but I see no reason why you can't use it to specify which tennant you want.
The only issue here is that Membership.ApplicationName is static, which means it's shared by all threads running in the App Pool. However, if you use some kind of lock around accessing it, then this shouldn't be a huge issue (though it could affect scalability at some level).
This would basically allow you to use the standard, out of the box membership provider without any changes. You just have ot make sure to guard the access calls.
You don't have to use the membership provider at all. Its simply provided as a quick and consistent way to get up and running. Some choose it because it supports multiple databases (universal membership providers include azure as well as sql ce, express, and full) but for others trying to map it to your applications rules can be more difficult than the <5 lines of code it takes to authenticate and issue your own forms auth ticket.
With that said I'm assuming you are using forms authentication. You can simply issue the ticket yourself. I would still program against an interface for this which the default MVC template should have, so simply add in a new tenant id.
With that said, I'd consider having unique names. It ensures you don't 'forget' to do an additional tenant check somewhere else in the app and tenant1\userBip and tenant2\userBip surprisingly end up stomping on each others record at some point.
True, testing should uncover this - if testing is complete : )