How do I return multiple identities in a token with Thinktecture.IdentityServer.45? - claims-based-identity

In the Thinktecture.IdentityModel.45 library, I can get a Microsoft.IdentityModel.Claims.ClaimsIdentityCollection by executing something like this:
Dim handler = New JsonWebTokenHandler()
handler.Configuration = config ' set elsewhere
Dim identities = handler.ValidateToken(handler.ReadToken(token))
We have a system where a user gets to login and then choose an organizational context they are part of. Each context should be representative of what is available in the token (one identity per organization with a collection of specific claims). How can I get the Thinktecture.IdentityServer.45 to return a token that contains multiple identities?

WIF is generally not designed for this. And only certain token types support this at all.

Related

ASP.NET core app authenticating with AAD: it is possible to retrieve additional user properties/attributes as claims?

I have created an ASP.NET Core application that successfully authenticates users with Azure AD and have seen that for an authenticated user an instance of type System.Security.Claims.ClaimsPrincipal is returned containing a single identity of type System.Security.Claims.ClaimsIdentity with a Type property valued "preferred_username" that carries the user's UPN. Among the claims that are returned there is for example one with its Type property valued "name" which seems to contain the user's display name. I was wondering if there is a way to have other users' attributes/properties also returned in the form of claims.
I was wondering if there is a way to have other user's
attributes/properties also returned in the form of claims.
Obviously you can retrieve optional claims within your token using azure active directory. To achieve that you would need few settings in Token configuration under azure active directory blade.
What Additional Claim can be added:
Currently, you can include these optional claims in your both idToken, accessToken and saml2Token
Settings For Optional Claims:
If you would like to include additional claims within your token you ought to configure as following:
Select Token configuration in your app:
Select Add optional claim and Include your claims:
You should have profile access permission:
Check your Manifest if the claims added accordingly:
Now You can Call Optional Claims which are available ClaimTypes Class:
Note: You can check the available claims fields witin ClaimTypes Class here.
Code Snippet:
You can implement within your application as following:
var username = HttpContext.User.Identity.Name;
var givenName = HttpContext.User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.GivenName)?.Value;
var email = HttpContext.User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value;
var country = HttpContext.User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Country)?.Value;
Note: If you would like to know more details on optional claims you could check our official document here.

How can I search for ldap fields when using ActiveDirectoryRealm in Apache Shiro?

We use Apache Shiro to authenticate and authorize users using our active directory.
Authenticating the user and mapping groups works just fine using the following config:
adRealm = org.apache.shiro.realm.activedirectory.ActiveDirectoryRealm
adRealm.searchBase = "OU=MYORGANIZATION,DC=MYDOMAIN,DC=COM"
adRealm.groupRolesMap = "CN=SOMEREADGROUP":"read","CN=SOMEMODIFYGROUP":"modify","CN=SOMEADMINGROUP":"admin"
adRealm.url = ldaps://my.ad.url:636
adRealm.systemUsername= systemuser
adRealm.systemPassword= secret
adRealm.principalSuffix= #myorganization.mydomain.com
I can authenticate in Shiro using the following lines:
String user = "someuser";
String password = "somepassword";
Subject currentUser = SecurityUtils.getSubject ();
if (!currentUser.isAuthenticated ()){
UsernamePasswordToken token = new UsernamePasswordToken (user,
password);
token.setRememberMe (true);
currentUser.login (token);
}
We now want to get more user information from our ActiveDirectory. How can I do that using Apache Shiro? I was not able to find anything about it in the documentation.
In the source code of ActiveDirectoryRealm I found this line:
NamingEnumeration answer = ldapContext.search(searchBase, searchFilter, searchArguments, searchCtls);
So the first part of the answer is clear: use the ldapContext to search something in it. But how can I retrieve the LdapContext?
It depends on what you are trying to do. Are you just trying to reuse the context to run a query for something other then authentication or authorization? Or are you trying to change the behavior of the query in the AD realm?
If the latter, you would need to extend the ActiveDirectoryRealm and override the queryForAuthorizationInfo() method.
Are you implementing something that is custom for your environment?
(updated)
A couple things:
The realm has access to the LdapContext in the two touch points: queryForAuthenticationInfo() and queryForAuthorizationInfo(), so if you extend the AD realm or AbstractLdapRealm you should already have it. You could change the query to return other info and add the extra info to your Principal. Then you have access to that info directly from your Subject object.
Your realms, are not required to be singletons.
If you want to do some other sort of user management (email all users with a given role, create a user, etc). Then you could create a LdapContextFactory in your shiro.ini, and use the same instance for multiple objects.
[main]
...
ldapContextFactory = org.apache.shiro.realm.ldap.JndiLdapContextFactory
ldapContextFactory.systemUsername = foobar
ldapContextFactory.systemPassword = barfoo
adRealm = org.apache.shiro.realm.activedirectory.ActiveDirectoryRealm
adRealm.ldapContextFactory = $ldapContextFactory
...
myObject = com.biz.myco.MyObject
myObject.ldapContextFactory = $ldapContextFactory
This would work well if myObject is interacting with other Shiro components, (responding to events, etc), but less so if you need access to it from another framework. You could work around this by some sort of static initialization that builds creates the ldapContextFactory, but in my opinion, this is where the sweet spot of using the shiro.ini ends, and where using Guice or Spring shines.

DropboxUnlinkedException but the session already had token inside and user didn't revoke the access

My problem is I have existing user in database which store the key and secret from the first authentication. I wish to reuse it again when I come back. For the first time authentication, everything working fine. I can use every method call from Dropbox API and the Token(key and secret) was stored in database.
I come back to app and get the Token from database, set it to the session, link current session with API.
session = new WebAuthSession(appKeys, ACCESS_TYPE);
api = new DropboxAPI<WebAuthSession>(session);
String userKey = dropboxUserObj.getUserKey(); //Key from database
String userSecret = dropboxUserObj.getUserSecret();//Secret from database
AccessTokenPair userAccessTokenPair = new AccessTokenPair(userKey, userSecret);
session.setAccessTokenPair(userAccessTokenPair);
It return DropboxUnlinkedException to me when I want to get user data from api using
String userDisplayName = api.accountInfo().displayname;
I have checked on debug mode. Api was linked with the current session. The current session stored Appkey and user's token and correct access type. The point that I doubt is I saw "client = null". I maybe forgot something but I check them all, try every possibilities I can think of but it still return me "DropboxUnlinkedException" which mean I haven't set an access token pair on the session and I didn't revoke access for sure.
Please help me figure out...
I added a screenshot maybe it can illustrate my problem

Developing a Service with API Keys (starting point)

Looked on google and couldn't find anything.
Any good resources to get started designing my backend for a RESTless webapp thats going to rely heavily on API keys.
I know how to write restless webservices etc, just never used API-keys. Generally do people just generate guids for users etc?
Here's how I'm creating API keys for a web service:
string CreateApiKey(int length)
{
var bytes = new byte[length * 2];
using (var rng = new RNGCryptoServiceProvider())
rng.GetBytes(bytes);
var chars = Convert.ToBase64String(bytes)
.Where(char.IsLetterOrDigit)
.Take(length)
.ToArray();
var key = new String(chars);
return key;
}
GUID's are typically not "random" enough and can be easily guessed by the bad-guys.
Take some "random" data like the user's password hash, some random numbers and run the result through sha1 or a similar hash function.
If you want one API key per account, simply add it to the account metadata table. Otherwise use a table linked to the accountIds to store the api keys.
Server side use a cache using the api-key as the key to store temporarily the account metadata so you only need to go to the db once per session.
And of course everything must go over https to avoid that the API key be stolen.
Now if your service is "session" oriented you can consider using a temporary session key so you do not need to expose the API key. Look for public key encryption to investigate this further.

Adding custom roles - VB 2008 Winforms

I have a winforms (VB 2008) based app that I'm developing and I want to use custom roles for user access.
Application Layout:
I have a Main form that opens a login form when certain actions occur. The Login form intern uses an authentication class that I've created, to authenticate users and set access rights. On my Applications settings page, I have Authentication Mode set to Application-defined because I cannot use Windows Authentication in the environment where this will be deployed.
The application uses a MS SQL 2005 db and the 3 tables I'm using in the authentication process are the User_Account , User_Roles and User_Access tables. The combination of an account in the User_Account and the roles within the User_Roles table are the bases for the User_Access table. Using the User_Access table is how I assign access to the various functions within the application
Authentication Method:
To authenticate a user, I'm using the "My.User.CurrentPrincipal" (Code below) method. The My.User object works great and allows the use of "My.User.Name" property throughout the app when referring to the currently authenticated user.
Access Method:
In order to set the current users access levels I'm using a function within my Authentication class and passing in My.User.Name as a variable. The function uses a Dataset Table Adaptor and a Select Case statement inside a For loop to assign all the access levels for the user (Function code below).
My Problem:
This method of assigning access rights to a user does work but it's not persistent throughout the application as the My.User object is. I would like to find a way to create custom roles through the My.User object using its .IsInRole property. I would like to have these roles dynamically created using my User_Roles table.
This would allow the custom roles to be used throughout my application using the My.User.IsInRole("MyRole") syntax ...similar to how I'm currently able to use My.User.Name. Unfortunately the only roles I can currently validate against are the built in Windows type accounts (Adminisrator ...ect.).
I have found lots of information and examples related to ASP.Net as well as setting up Winforms Windows authentication but nothing so far directly related to my issue.
I think there's a way to accomplish this...but I have not been able to find it. Any help would be greatly appreciated!!
Thank you for your help!
'User Authentication example:
If Authenticate.CheckPassword(tbxUserName.Text, strPassword) Then
My.User.CurrentPrincipal = New GenericPrincipal(New GenericIdentity(tbxUserName.Text), Nothing)
'Access assignment example:
Public Shared Function GetUser(ByVal strUsername As String) As Authenticate
Using UserAdapter As New dbUserTableAdapters.User_AccountsTableAdapter()
Dim UserTable As dbUser.User_AccountsDataTable = UserAdapter.GetByUser(strUsername)
Dim tempUser As New Authenticate() _
With {.ID = UserTable(0).id, _
.Username = UserTable(0).User_Name, _
.Password = UserTable(0).id}
Using AccessAdapter As New dbUserTableAdapters.User_AccessTableAdapter()
Dim AccessTable As dbUser.User_AccessDataTable = AccessAdapter.GetByUser(tempUser.ID)
For c As Integer = 0 To AccessTable.Rows.Count - 1
Select Case AccessTable(c).Role_Id
Case RoleType.SysAdmin
tempUser.AllowSysAdmin = True
Case RoleType.Maintenance
tempUser.AllowMaintenance = True
Case RoleType.ReportAll
tempUser.AllowRptAll = True
Case RoleType.ReportException
tempUser.AllowRptExceptions = True
Case RoleType.EventManagment
tempUser.AllowEventStart = True
Case Else
End Select
Next
Return tempUser
End Using
End Using
End Function
I think you need to implement a custom IPrincipal object which accesses your SQL table. Try this page.
Edit:
First, have a look at the definitions of IIdentity and IPrincipal. You'll note that IIdentity doesn't have a 'Role' property defined. They've chosen to implement an additional property called Role on their implementation of IIdentity (SampleIIdentity) and then they've used it from their implementation of IPrincipal. What I'm suggesting is that you implement your own Role property (which queries your existing table) and returns one (or an array) of a Role type you define yourself. Then in your implementation of IPrincipal, you can code IsInRole to query the new Role property. Hopefully that makes more sense that my rather skimpy answer.