How to authenticate against a specific Organization? - stormpath

I'm trying to build a multi-tenant application using Stormpath. The stack being used is Angular + Express. I'm using the 'Directory-per-Organization' strategy to organize my multi-tenant accounts. My Login form has a 'Organization ID' form field for user to specify the organization’s nameKey.
Is there a specific format in which this field needs to be passed to the stormpath-express backend? Stormpath-Angular SDK has no mention of this. Assuming there is no specific format, I tried adding a preLoginHandler on the stormpath-express side to retrieve the org Id form field mentioned above and set a {accountStore : {nameKey : myOrgNameKey }} on the request body. This however does not authenticate against the specified organization. Instead, it tries to match against all the organizations mapped to the application. I tested this my typing in invalid random strings for Org ID field.
As an aside, Stormpath’s site (api.stormpath.com/login) too does not seem to authenticate against the specified tenant Key. As long as the username and password credentials are fine, I can type in any string in the tenant field and it seems to log me in fine.
I want the username-password credentials to be checked only against the specified organization key and not against all the organizations mapped to the application. How do I go about this ?

Related

Azure AD v2 with Azure App Registration missing optional email claim in ID Token for directly assigned user

I am migrating my asp net core MVC web app hosted in Azure App service with Azure AD IAM from v1 to v2. When a user logs in I create/update a local user account in my database which contains the user email. The problem I have is the email claim which is now an optional claim in v2 is null so my I cannot insert a new user record in my local database.
I have been through the MS documentation and configured my optional claims in app registration manifest etc but it does not work. I have tried all 3 claim variations (email, verified_primary_email, verified_secondary_email) but nothing comes through. However the optional claims for given_name and family_name are working as expected so the configuration must be right. How can I get email to work?
Below is my configuration and result.
App Registration Manifest
App Registration Permissions
User Profile Setup (email configuration for directly assigned member)
Returned Claims
Startup Config (adding email scope)
services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => Configuration.Bind("AzureAd", options));
services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>
{
options.Authority += "/v2.0/";
options.Scope.Add("email");
options.TokenValidationParameters.ValidateIssuer = true;
// Set the nameClaimType to be preferred_username.
// This change is needed because certain token claims from Azure AD v1.0 endpoint
// (on which the original .NET core template is based) are different in Microsoft identity platform endpoint.
// For more details see [ID Tokens](https://learn.microsoft.com/azure/active-directory/develop/id-tokens)
// and [Access Tokens](https://learn.microsoft.com/azure/active-directory/develop/access-tokens)
options.TokenValidationParameters.NameClaimType = "preferred_username";
}
Signin Request (including email scope)
https://login.microsoftonline.com/28f6d551-***-7f402200e732/oauth2/v2.0/authorize
?client_id=08fde457-***-7b0eebc5e4e2
&redirect_uri=https%3A%2F%2Flocalhost%3A44308%2Fsignin-oidc
&response_type=id_token
&scope=openid%20profile%20email
&response_mode=form_post
&nonce=637023698441049167.ZWZlMGQ1MzctZDVmMi00OGZlLTg5YzYtMjczOWIxNzlhYjI0MzdiNGI2YzMtZTFjYi00MDMxLWFkODItNmExNDlmZTQ2MWE1&state=CfDJ8Em5zZW9XwdJkjHAUddTGuvClgDAA0NFafwsZBlTbau2qhMPcRBM36vSSzFEw7GME28L57BSQyGo8WNNzd61_bciTunD0R15oC__96_tXlWaPmk3jZkOpA2VUoiwG9XrZjfDOTQIWAzS2IuqUu5gXWU8dgK7YEfyAuRwVmCQlWqlt94HPUwMSsSJpMsdlB6HD3Tb0DaPCspo2BiYga-5LWDQ5FBnFCpxPAdLNa6LTHHNtKjUbG7YNX4oEKUBhWtxQ0Kh1CakChUFCpmMzAmBgyN5Hh_-nk3BrO3V6PrgbvDsGO6QNip5hCwiDd92gexrLYwS_UeKruPKCQMZBWZ9LnSRaNnTDN1483Abk75JiH19XPJwexmQ5aMa1KZwcde4axF-tb2cmnwWY8O4NGhRiQDSISZJAuXmHWBtAeNhnLHN659vbeiW8mo5aWD65NcfhLtio2odxvLFh3JZGoRwHCtKzu9fq8v4w7IN2f1bNb8zPdo7Lw_GREiYKs1twibIh305tja30MMRS3oAE1hKQE20A4wtmxVACuPZ201SRkFg8OHl-Iz6e4Pa41P4gT-F2jpzL1zqklDw0tzaYq68uVlqmeCY5T9vo2qkfvRuIdpyyTGu8pdi-Z6sVvIpIxPllQ
&x-client-SKU=ID_NETSTANDARD2_0
&x-client-ver=5.3.0.0
Returned Token (email claim still missing)
UPDATE 2019-08-26
I suspect the issue is with the user account instead. As a directory administrator I create the user accounts within AAD and enter the Email and Alternate Email values. However when I log in to AAD as the end user and view my profile I can see that Email field is blank and only Alternate Email field is populated as shown below. I'm not sure why the user profile is not picking up the set email address but it's a problem and I now have to find a way of getting the Alternate Email into the ID Token instead. How can this be done?
Email Addresses in AAD
Email Addresses in User Profile
Just some findings and suggestions, might not be a exact answer.
Based on the documentation(optional claims) from Microsoft:
A. The claim's name is email.
B. As you were migrating from V1 to V2, I just tested the V2 (For convenience, I tested with a REST API tool). By adding the openid and email scopes, I can get the email claim in id token.
C. Analyze the id token in jwt.io, I can get the email claim:
I did not modify the manifest, just added openid and email scopes. You can have a try.

Changing request level for google project

How do I lower the requested access level of an existing google project?
It's currently asking for:
View your email address
View your basic profile info
Manage your contacts
When all I really want is to authenticate a user for login purposes, and I think all I need for that is:
Have offline access
One of the parameters you are passing when you create a credential is called scope, and contains a list of each of the services your users must authorize.
From the OAuth 2.0 docs, scope contains a string or iterable of strings. Change it to the new scopes you want.

MVC Multi Tennat Application how to add sub site

I have an intranet application for which the URL is as follows
http:\\ServerName]\RunLog\
I am adding another department/tenant/group of users which will utilize the same instance of the application and same database. Their data will be different from the existing users. I am planning to add new column foreign key in each table to identify the specific tenant. I authenticate users windows authentication. I am thinking that the access to the application will be as follows
http:\[ServerName]\Platform1\RunLog
http:\[ServerName]\Platform2\RunLog
So for the above URL, how could I go about achieving that in the Application? I know how to make the table changes in SQL server, Updating the Entities, Updating the linq code in the controllers to pull up respective tennant data. Any help to get me started would be appriciated.
Kindly note that as you have given in your post, it is possible to identify the tenant's based on their URL. The table that contains the tenant details will also contain their url. So you will identify the tenant based on the URL. After identifying the tenant, we can authenticate the user's using the found tenant id / tenant code, get the tenant's configuration or settings using the same tenant id / tenant code.
I hope that you could have all the other entities of the application with a column called as TenantId. This will help you to fetch the data based on tenant. Your only change will be in the data access layer where you will filter the data that you retrieve from the Database.
Let me know if you have any other clarifications regarding the other specifics of this implementation.

Extending WSO2 Identity Server JDBCUserStoreManager to fit external user database

We have a requirement to authenticate users of a web application deployed in WSO2 Application Server against an existing external database. We are trying using WSO2 Identity Server for this.
Our db table containing users has two columns which make a username unique, clientid and usercode. i.e. usercode is not unique by itself but clientid+usercode is unique. Also our passwords are salted with PBKDF2. So I have extended the JDBCUserStoreManager to talk to our database and am able to store and retrieve passwords in PBKDF2.
But I cant figure out how I can get the client id from the login page to our extended JDBCUserStoreManager. i.e how can I access clientid stored in users session, from inside our custom JDBCUserStoreManager? If I can get the clientid from the session in there, I can use it in the sql queries to do the needful.
Any help in figuring this out is much appreciated..
You can enter the combination "clientid+usercode" as the username at the login page. Then the authenticator will pass that combination as the username to the doAuthenticate() method of your custom userstore manager. There you can split the client id and usercode from the username.

Storing necessary OpenID information

I'm trying to implement OpenID authentication for my site. Here's the scenario:
I want the user to be able to
login using just openId(user can just get verified by visiting openid provider. no need to create a custom account with email-password),
Via email/password (user has registered in site by filling out a form)
Attach open id(s) to his/her accounts (openids + email for one account).
Now I don't know what credentials I should store for open id. and not sure about the DB schema. Here's the database schema:
Table: Users
UserId => PK
... => Custom info. Not related to authentication.
Table: Authentication
AuthenticationId => PK
LoginId => (when custom site membership => email address) (when openId => openid unique address)
UserId => FK to Users.
Provider =>(when custom site membership => "CUSTOM") (when openId => openid provider address)
Password => filled when using custom membership. empty when using open id.
Now when a user logs in, whether by using openid/custom membership, I just look at authentication table and look for credentials and get the appropriate user. If no users exist, I create a new user and add an entry in authentication table.
The main question: Is storing Provider and LoginId (see the above comments to see what is being stored in these fields) enough for storing openid authentication? Should I store any additional data so that when the user returns I can authenticate him/her based on my saved data?
Do you suggest any other (more efficient) approach to implement this?
Thank you.
Store the ClaimedIdentifier for the openid user--not the Provider address. The Claimed Identifier is what the OpenID protocol verifies is unique for the user and also potentially provides portability across OpenID Providers.
Also, because OpenID 2.0's Claimed Identifiers may be deprecated by OpenID Connect (an unfinished successor to OpenID 2.0), it may also be in your best interest to record the OpenID Provider Endpoint URI and the email address asserted by the Provider in the user record. For now, do not use these as part of your authentication flow, but by recording them, you'll be able to later determine which email addresses you 'trust' (i.e. suppose you decide email addresses asserted by Google are trustworthy) and allow the user to thereby migrate their account to an OpenID Connect one using that verified email address. This will also mitigate against the danger of your web site's Realm (usually http://yourdomainname.com) changing and causing all your Google's user Claimed Identifiers to change, which can only really be recovered from via their email address, tragically.
I also recommend you use different tables for the different auth types. There are a couple of advantages here. The most important one is that architecturally it makes it more difficult to have introduce a security hole into your web site that might allow someone to enter in (for example) an OpenID into the username field and a blank password and have it show up as a database match and login without any real authentication happening. Secondly, it provides a more flexible model in case you want to add a third authentication mechanism rather than making your 'Authentication' table grow horizontally for all users. For example, OAuth 2.0 and "OpenID Connect" will each probably introduce new types of authentication to your site when you add support for them over the years, and adding new tables to handle the new types of data seem to fit better.
We just store the openid claim url. You may want to request additional information from the provider such as the user's name. The most important thing is to separate membership and authentication.
Our schema was
Profiles
--------
UserId
FirstName
LastName
etc.
Users
-----
Username
Password
Profiles.UserId is simply a string property that stores either the users internal username or their openId claim url, depending on how they registered.
Upon successful authentication (either using an internal username/password or external provider) we just set their authentication cookie using either their internal username or their claim url. Getting the user's profile is then just a matter of finding the profiler where (UserId == User.Identity.Name).
This has the advantage that a user can choose to change how they authenticate at any point (perhaps switching to an internal account or using a different provider).

Resources