{"id":2944,"date":"2014-08-26T00:34:19","date_gmt":"2014-08-26T07:34:19","guid":{"rendered":"http:\/\/www.cloudidentity.com\/blog\/?p=2944"},"modified":"2014-08-26T22:32:14","modified_gmt":"2014-08-27T05:32:14","slug":"the-common-endpoint-walks-like-a-tenant-talks-like-a-tenant-but-is-not-a-tenant","status":"publish","type":"post","link":"https:\/\/www.cloudidentity.com\/blog\/2014\/08\/26\/the-common-endpoint-walks-like-a-tenant-talks-like-a-tenant-but-is-not-a-tenant\/","title":{"rendered":"The Common Endpoint: Walks Like a Tenant, Talks Like a Tenant&hellip; But Is Not a Tenant"},"content":{"rendered":"<p>The common endpoint is one of the most powerful development features of AAD \u2013 unfortunately, it is also one of the least intuitive ones. In this post I will give you a brief taste of what it does, what it is useful for, and how ADAL surfaces its strange properties.<\/p>\n<h2>Azure AD Tenant Endpoints<\/h2>\n<p>You probably know all this already, but a quick refresher is never a bad thing.<\/p>\n<p>Every Azure AD tenant provides a bunch of endpoints that you can use to secure your applications, choosing between the various protocols AAD supports.<br \/>\nAlthough those endpoints are all referring to different protocols, they all follow the same basic pattern. In the immortal BNF notation, you could define that pattern as follows:<\/p>\n<p><span style=\"font-family: Consolas;\">&lt;protocol-endpoint&gt; ::= <span style=\"color: #00ff00;\">&lt;instance&gt;<\/span><\/span>&lt;tenant&gt;<span style=\"font-family: Consolas;\"><span style=\"color: #0000ff;\">&lt;protocol-specific-path&gt;<\/span><\/span><\/p>\n<p><span style=\"font-family: Consolas;\"><span style=\"color: #0000ff;\">&lt;protocol-specific-path&gt;<\/span> ::= <em>\u201c\/oauth2\/authorize?api-version=1.0\u201d<\/em> | <em>\u201c\/oauth2\/token?api-version=1.0\u201d<\/em> | <em>\u201c\/federationmetadata\/2007-06\/federationmetadata.xml\u201d <\/em>| \u2026<\/span><\/p>\n<p><span style=\"font-family: Consolas;\"><span style=\"color: #ff0000;\">&lt;tenant&gt;<\/span> ::=\u00a0 &lt;tenant-id&gt; | &lt;domain&gt;<\/span><\/p>\n<p><span style=\"font-family: Consolas;\">&lt;tenant-id&gt; ::= &lt;GUID&gt;<\/span><\/p>\n<p><span style=\"font-family: Consolas;\">&lt;domain&gt; ::<\/span> = &lt;hostname&gt;<\/p>\n<p><span style=\"font-family: Consolas;\"><span style=\"color: #00ff00;\">&lt;instance&gt;<\/span> ::= <em>\u201chttps:\/\/login.windows.net\/\u201d<\/em> | \u2026<\/span><\/p>\n<p>If you prefer things a tad less formal, we can think of some examples. For instance, if I want to obtain the OAuth2 authorization endpoint of my test tenant developertenant I can simply write:<\/p>\n<p><a href=\"https:\/\/login.windows.net\/developertenant.onmicrosoft.com\/oauth2\/authorize?api-version=1.0\"><span style=\"font-family: Consolas;\">https:\/\/login.windows.net\/<span style=\"color: #ff0000;\">developertenant.onmicrosoft.com<\/span>\/oauth2\/authorize?api-version=1.0<\/span><\/a><\/p>\n<p>Another way I can refer to the exact same endpoint is the following:<\/p>\n<p><a href=\"https:\/\/login.windows.net\/developertenant.onmicrosoft.com\/oauth2\/authorize?api-version=1.0\"><span style=\"font-family: Consolas;\">https:\/\/login.windows.net\/<span style=\"color: #ff0000;\">6c3d51dd-f0e5-4959-b4ea-a80c4e36fe5e<\/span>\/oauth2\/authorize?api-version=1.0<\/span><\/a><\/p>\n<p>This is the exact same endpoint \u2013 I am simply choosing a different way to identify the corresponding tenant. The advantage of using the domain is mostly that it\u2019s human readable and easier to remember than a GUID. The tenantID, on the other hand, has good properties like immutability (a domain can be discarded, a tenantID is forever), is non-reassignable (discarded domains might get bought by other orgs, messing with your endpoints) and provides a single identifier to construct a stable endpoint no matter how many domains you registered.<\/p>\n<p>Where do I find the tenantID? There are various places to pick it up from. The easy one is via the Azure portal: all endpoints are listed via the view endpoints button on the bottom common bar in the AAD\/tenant\/applications page. Those endpoints are expressed via the tenantID.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/08\/image.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/08\/image_thumb.png\" alt=\"image\" width=\"640\" height=\"454\" border=\"0\" \/><\/a><\/p>\n<p>Another way of retrieving that, which I favor because it does not require me to sign in, is to hit the public ws-federation metadata endpoint of the tenant \u2013 which is public. You can build that URL using the domain (which I usually remember), but the content of the metadata will always refer the tenantID. For example, if I follow<\/p>\n<p><a title=\"https:\/\/login.windows.net\/6c3d51dd-f0e5-4959-b4ea-a80c4e36fe5e\/federationmetadata\/2007-06\/federationmetadata.xml\" href=\"https:\/\/login.windows.net\/developertenant.onmicrosoft.com\/federationmetadata\/2007-06\/federationmetadata.xml\">https:\/\/login.windows.net\/developertenant.onmicrosoft.com\/federationmetadata\/2007-06\/federationmetadata.xml<\/a><\/p>\n<p>I\u2019ll land on the following document:<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/08\/image1.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/08\/image_thumb1.png\" alt=\"image\" width=\"640\" height=\"169\" border=\"0\" \/><\/a><\/p>\n<p>Et voila\u2019, the highlighted text is the tenantID. Also note the entityID, which is in itself a URI parametric in respect to the tenantID: it will come in handy later.<\/p>\n<p>Anyway: once you have your endpoints, you can plug them in your favorite development stack and use them to your heart\u2019s content (usually to request tokens).<\/p>\n<h2>Late Binding a Tenant<\/h2>\n<p>The above is all fine and dandy if you are writing a line of business app, where the organization you want to authenticate with is known at development time.<\/p>\n<p>However, that does leave out a very large class of important applications: SaaS and multitenant applications. My recent favorite example is <a href=\"http:\/\/www.windowsphone.com\/en-us\/store\/app\/org-navigator\/84975f22-2c23-4a90-9a5e-cde950e8a084\">Org Navigator<\/a>, the <a href=\"https:\/\/www.cloudidentity.com\/blog\/2014\/07\/28\/org-navigator-a-mobile-app-leveraging-azure-ad-graph\/\">little app I wrote few weeks ago that allows you to search for users in an Azure AD tenant<\/a>.<\/p>\n<p>While it sleeps its dreamless sleep in its cell up in the Windows Store cloud, Org Navigator does not know which AAD tenant it will need to search. When you download and install it, Org Navigator <em>still<\/em> does not know which tenant it should work with. However, when you first launch the app and you try your first query \u2013 BAM: it presents you the usual AAD credential experience. You sign in with one user from the tenant you want to target, and you\u2019re in: from that moment on, Org Navigator knows which AAD tenant to query (and knows how to get the tokens needed to do so).<\/p>\n<p>How did I achieve this behavior when developing Org Navigator? What endpoint rendered the AAD credential experience, given that at that point the app did not know which domain or tenantID to use?<br \/>\nIf your short term memory is not as bad as mine these days, you already guessed what made this possible: the common endpoint.<\/p>\n<p>The BNF I provided earlier wasn\u2019t really complete: the &lt;tenant&gt; entry should have been<\/p>\n<p><span style=\"font-family: Consolas;\"><span style=\"color: #ff0000;\">&lt;tenant&gt;<\/span> ::=\u00a0 &lt;tenant-id&gt; | &lt;domain&gt; | <em>\u201ccommon\u201d<\/em><\/span><\/p>\n<p>In a nutshell, <em>common<\/em> is a convention used to tell AAD \u201cI don\u2019t yet know which tenant should be used. Please render a generic credential gathering experience, and we\u2019ll figure out the tenant depending on what account the user enters\u201d.<\/p>\n<p>That is precisely what I did in Org Navigator. I arranged for the very first authentication operation to go against the authority (in ADAL parlance) <a href=\"https:\/\/login.windows.net\/common\">https:\/\/login.windows.net\/common<\/a>, and that afforded me the behavior described above (for a more detailed walkthrough see <a href=\"https:\/\/www.cloudidentity.com\/blog\/org-navigator\/\">Org Navigator\u2019s help page<\/a> \u2013 or <a href=\"http:\/\/www.windowsphone.com\/en-us\/store\/app\/org-navigator\/84975f22-2c23-4a90-9a5e-cde950e8a084\">download the app and try it on your own tenant or the graph test tenant<\/a>!).<br \/>\nOther canonical uses can be observed in our <a href=\"https:\/\/github.com\/AzureADSamples\/?query=multitenant-o\">multitenant Web samples<\/a> \u2013 in particular, the sign in and sign up links. More details later.<\/p>\n<p>That is pretty handy! The user does the work for you, effectively late binding the tenant. However, there are a couple of things to keep an eye on.<\/p>\n<ul>\n<li>For line of business applications you do NOT want to late bind the tenant, in fact you want to ensure that the caller comes from your specific tenant and no other! In that case, use of common is not appropriate. More details on the OWIN section below.<\/li>\n<li>If the user enters the credentials of an account that is a guest in multiple tenants, AAD will not know which one to pick to get the token. As of today, the call will fail.<\/li>\n<\/ul>\n<p>That said, let\u2019s take a look at some practicalities of using common with web apps (via our OWIN middleware) and via ADAL.<\/p>\n<h2>OWIN Middleware and the Common Endpoint<\/h2>\n<p>As the post title says, common is NOT a tenant: rather, it is a convention that is used in place of a tenant for driving the real tenant identification process.<br \/>\nGiven its placement in the endpoints URI template, however, it is very hard not to think about it as a tenant and just use it everywhere one would use a real AAD tenant. In fact, that\u2019s largely the way in which we use it: however we do need to perform some extra steps to accommodate for common\u2019s peculiar behavior.<\/p>\n<p>Let\u2019s make a practical example. Let\u2019s say that we want to write a multi tenant web app secured via OpenId Connect which can sign users from any tenant. In order to late bind the tenant, we could write the following OWIN auth middleware init:<\/p>\n<pre class=\"csharpcode\"><span class=\"kwrd\">public<\/span> <span class=\"kwrd\">void<\/span> ConfigureAuth(IAppBuilder app) {          \r\n         <span class=\"kwrd\">string<\/span> ClientId = ConfigurationManager.AppSettings[<span class=\"str\">\"ida:ClientID\"<\/span>]; \r\n         <span class=\"kwrd\">string<\/span> Authority = <span class=\"str\">\"https:\/\/login.windows.net\/common\/\"<\/span>; \r\n         <span class=\"rem\">\/\/ ...<\/span>\r\n\r\n         app.UseOpenIdConnectAuthentication( \r\n         <span class=\"kwrd\">new<\/span> OpenIdConnectAuthenticationOptions \r\n         { \r\n           ClientId = ClientId, \r\n          Authority = Authority, \r\n         }\r\n\/\/ ...<\/pre>\n<p>This would indeed cause the desired behavior\u2026 almost. If you\u2019d run the app you\u2019d be able to sign in with any user from any tenant, but upon authentication with AAD, the app would reject the call. Why?<br \/>\nRecall how we managed to keep the object model of the OWIN authentication middleware so compact? That\u2019s right, we use the tenant coordinates to read from metadata documents the extra info we need to validate tokens. Now, the common endpoint does expose metadata as well \u2013 but they are somewhat incomplete. For example, if I open the OpenId Connect discovery doc I see the following:<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/08\/image2.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/08\/image_thumb2.png\" alt=\"image\" width=\"640\" height=\"172\" border=\"0\" \/><\/a><\/p>\n<p>Whereas in a real tenant you\u2019d find actual tenantid values, the common endpoint cannot offer that given that the actual tenant that will be used is undefined. The \u201c{tenantid}\u201d string is clearly a placeholder rather than a real value.<br \/>\nThe \u201cissuer\u201d value in that doc is the string that the OWIN middleware will use in its default validation logic to validate the \u201cissuer\u201d value of incoming tokens . Clearly that cannot work, given that once the user enters an account from a specific tenant the issuer value will be something like \u201c<a title=\"https:\/\/sts.windows.net\/6c3d51dd-f0e5-4959-b4ea-a80c4e36fe5e\" href=\"https:\/\/sts.windows.net\/6c3d51dd-f0e5-4959-b4ea-a80c4e36fe5e\">https:\/\/sts.windows.net\/6c3d51dd-f0e5-4959-b4ea-a80c4e36fe5e<\/a>\/\u201d which clearly does not match \u201c<a title=\"https:\/\/sts.windows.net\/{tenantid}\/\" href=\"https:\/\/sts.windows.net\/{tenantid}\/\">https:\/\/sts.windows.net\/{tenantid}\/<\/a>\u201d.<\/p>\n<p>If we\u2019d be working with WS-Federation, the music would be the same. This is common\u2019s ws-fed metadata:<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/08\/image3.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/08\/image_thumb3.png\" alt=\"image\" width=\"640\" height=\"147\" border=\"0\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>What to do? The only way around this is <strong>to override the default issuer validation<\/strong>, which is meant to work with fixed-tenant line of business apps, <strong>with your own validation logic.<\/strong><\/p>\n<p>The OWIN middleware makes it exceedingly easy. For example, in our multitenant web app sample we have a sign up experience which dynamically adds new tenants (or even individuals from arbitrary tenants). There, we turn off the default validation (via TokenValidationParameters\/ValidateIssuer=false) and we inject custom logic in the SecurityTokenValidated notification, late in the pipeline because in this case we need to have the user info available. Code <a href=\"https:\/\/github.com\/AzureADSamples\/WebApp-MultiTenant-OpenIdConnect-DotNet\/blob\/master\/TodoListWebApp\/App_Start\/Startup.Auth.cs\">here<\/a>.<br \/>\nIf in your heuristic you are only interested in the issuer, you can directly inject your own validation logic in the IssuerValidator notification of the TokenValidationParameters.<br \/>\nOr even further, if for some reason you are not interested in restricting access to your app per tenant you can simply turn off issuer validation and not provide any extra validation logic (if you think you\u2019re in this case, think long and hard about it to ensure that\u2019s truly OK for your scenario to skip that validation!).<\/p>\n<p>That\u2019s pretty much what there is to know about the common endpoint and web apps.<\/p>\n<h2>ADAL and the Common Endpoint<\/h2>\n<p>The common endpoint is easy to use with ADAL: you just pass it to your AuthenticationContext as the authority, and the authentication experience will follow the behavior described. However common is not a real tenant, and ADAL needs to perform some extra steps here. Namely: <strong>once the authentication takes place and a tenant from a real tenant is returned, the AuthenticationContext\u2019s authority is automatically reassigned to that real tenant<\/strong>.<\/p>\n<p>Below you can see an example in which the authority starts as common, but as I sign in with a user from developertenant the authority changes accordingly.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/08\/image4.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/08\/image_thumb4.png\" alt=\"image\" width=\"640\" height=\"117\" border=\"0\" \/><\/a><\/p>\n<p>Leaving the authority as \u201ccommon\u201d would cause all sorts of problems, given that the token so obtained is cached under the real authority: caching under common would not make much sense, given that common can be used multiple times against multiple tenants \u2013 which would all end up under the same \u201cauthority\u201d and triggering all sorts of weirdness\/security issues at cache retrieval time.<\/p>\n<p>Note, this is particularly important for apps that persist their cache across multiple runs.\u00a0Your AuthenticationContext should use common exclusively when you truly don&#8217;t know which tenant to use.\u00a0That means that on the\u00a0very first run\u00a0you can use common to let the user select their tenant of choice, however after that you should track the tenant you find in AuthenticationResult and use it if you happen to create new AuthenticationResults instances afterwards. That is typically the case when you close and re-open an app. Remember: <strong>if you don&#8217;t do that, you will never hit the cache and your user will always be prompted, every time<\/strong>.<br \/>\nYou can choose to save the tenantID in your own store and use it at AuthenticationContext init time. An alternative is to always init AuthenticationContext\u00a0with common, but once you have the instance in memory to check if the cache does contain already a token for a given tenant (via TokenCache.ReadAllItems +LINQ) &#8211; if it does, you can dispose of the common-inited AuthenticationContext\u00a0and create a new AuthenticationContext\u00a0which uses the tenant from the cached token; otherwise, you keep the common around so that it will do its late binding magic on the first call. A bit more cumbersome than the case in which you save the tenantID in your own custom location, but it does work as well.<\/p>\n<h2>Wrap<\/h2>\n<p>The common endpoint is a great feature, I\u2019d daresay indispensible in multitenant scenarios. The way in which it is represented (a parametric tenant) allows you to take advantage of its capabilities using a familiar approach, e.g. treating common as a tenant. There are some differences that eventually you have to handle, however I hope that this post showed they really aren\u2019t rocket science. Let us know if you have feedback or you encounter specific issues, otherwise\u2026 happy coding!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The common endpoint is one of the most powerful development features of AAD \u2013 unfortunately, it is also one of the least intuitive ones. In this post I will give you a brief taste of what it does, what it is useful for, and how ADAL surfaces its strange properties. Azure AD Tenant&#8230;<\/p>\n","protected":false},"author":1,"featured_media":2937,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-2944","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/2944","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/comments?post=2944"}],"version-history":[{"count":5,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/2944\/revisions"}],"predecessor-version":[{"id":2952,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/2944\/revisions\/2952"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media\/2937"}],"wp:attachment":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media?parent=2944"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/categories?post=2944"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/tags?post=2944"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}