{"id":1519,"date":"2013-03-02T02:00:03","date_gmt":"2013-03-02T11:00:03","guid":{"rendered":"http:\/\/www.cloudidentity.com\/blog\/?p=1519"},"modified":"2013-03-02T02:04:47","modified_gmt":"2013-03-02T11:04:47","slug":"url-urn-uri-oh-my","status":"publish","type":"post","link":"https:\/\/www.cloudidentity.com\/blog\/2013\/03\/02\/url-urn-uri-oh-my\/","title":{"rendered":"URL, URN, URI: Oh My!"},"content":{"rendered":"<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/03\/Untitled.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"Untitled\" alt=\"Untitled\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/03\/Untitled_thumb.png\" width=\"640\" height=\"364\" border=\"0\" \/><\/a><\/p>\n<p>[does this sound like common sense to you? Fantastic, please skip this post in its entirety. But lately I am stumbling in people confused about this <em>every day<\/em>, hence I going to write a post and start pointing them here]<\/p>\n<p>Let me get this straight right away: \u201cURL\u201d and \u201cURI\u201d are NOT interchangeable terms. Given that those are cornerstone concepts of the entire Web-based authentication castle, confusion and misunderstandings in their respective roles and functions can come at a steep price. For the same reason, in this post I am going to cut my usual language flourish in favor of pretty blunt statements. I\u2019ll also avoid trivia like expanding acronyms and similar, you can read the original specs for more details.<br \/>\nThat said:<\/p>\n<ul>\n<li>A UR<strong><span style=\"color: #ff0000;\">I<\/span><\/strong> is an identifier. It is meant to <em>identify <\/em>a resource of any kind, literally anything you can think of. <em>It\u2019s just a name <\/em>following some syntax (more below).<\/li>\n<li>A UR<strong><span style=\"color: #ff0000;\">L<\/span><\/strong> is a special kind of URI which is meant to specify the <em>location<\/em> of a resource available on the Internet.<\/li>\n<\/ul>\n<p>Concretely, the key difference between the two is: a URL <em>always<\/em> refers to something that is network-addressable,\u00a0 whereas a URI is a logical identifier which might have no endpoint or network-level manifestation whatsoever.<\/p>\n<p>The common rule of thumb is that if you paste a URL in a browser, you always get something back other than an error. Not really true, given that you might not be authorized or the corresponding resource might not support a straight GET, but it should give the idea. Examples of URL? Below:<\/p>\n<ul>\n<li><a href=\"http:\/\/127.0.0.1:81\/\">http:\/\/127.0.0.1:81\/<\/a><\/li>\n<li><a href=\"https:\/\/localhost:34534\/Api\/Add\/a\/2\/b\/7\">https:\/\/localhost:34534\/Api\/Add\/a\/2\/b\/7<\/a><\/li>\n<li><a href=\"ftp:\/\/host.com\">ftp:\/\/host.com<\/a><\/li>\n<li><a href=\"file:\/\/\/C|\/temp\/readme.txt\">file:\/\/\/C|\/temp\/readme.txt<\/a><\/li>\n<li><a href=\"mailto:vittorio@contoso.com\">mailto:vittorio@contoso.com<\/a><\/li>\n<li><a href=\"https:\/\/lefederateur.accesscontrol.windows.net\/FederationMetadata\/2007-06\/FederationMetadata.xml\">https:\/\/lefederateur.accesscontrol.windows.net\/FederationMetadata\/2007-06\/FederationMetadata.xml<\/a><\/li>\n<li><a href=\"https:\/\/accounts.accesscontrol.windows.net\/929bfe53-8d2d-4d9e-a94d-dd3c121183b4\/v2\/wsfederation\">https:\/\/accounts.accesscontrol.windows.net\/929bfe53-8d2d-4d9e-a94d-dd3c121183b4\/v2\/wsfederation<\/a><\/li>\n<li><a href=\"https:\/\/vibro.azurewebsites.net\">https:\/\/vibro.azurewebsites.net<\/a><\/li>\n<\/ul>\n<p>All pretty concrete stuff, which your browser (or Web API client, FTP client, mail client, etc) would use to obtain the corresponding resource. Not much to explain here.<br \/>\nWant to see some examples of URI? Well, technically all of the above were URI, given that URLs are a subset of the larger URIs set. So, how about some \u201cpure\u201d URIs meant to identify, as opposed to locate?<\/p>\n<ol>\n<li><a href=\"http:\/\/schemas.xmlsoap.org\/ws\/2005\/05\/identity\/claims\/name\">urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect<\/a><\/li>\n<li><a href=\"http:\/\/www.w3.org\/2001\/04\/xmldsig-more#rsa-sha256\">http:\/\/www.w3.org\/2001\/04\/xmldsig-more#rsa-sha256<\/a><\/li>\n<li>\u00a0<a href=\"http:\/\/schemas.xmlsoap.org\/ws\/2005\/05\/identity\/claims\/name\">http:\/\/schemas.xmlsoap.org\/ws\/2005\/05\/identity\/claims\/name<\/a><\/li>\n<li><a title=\"https:\/\/sts.windows.net\/929bfe53-8d2d-4d9e-a94d-dd3c121183b4\/\" href=\"https:\/\/sts.windows.net\/929bfe53-8d2d-4d9e-a94d-dd3c121183b4\/\">https:\/\/sts.windows.net\/929bfe53-8d2d-4d9e-a94d-dd3c121183b4\/<\/a><\/li>\n<li>urn:poormansactassample<\/li>\n<li><a href=\"https:\/\/vibro.azurewebsites.net\">https:\/\/vibro.azurewebsites.net<\/a><\/li>\n<\/ol>\n<p>I guess that for some of you the entries in this list looks less familiar. Let\u2019s look at each of those in some detail, and it will become clear why identification and location are radically different concepts.<\/p>\n<p>Entry #1 is the identifier of a SAML protocol binding. I took it from a Windows Azure AD metadata file, from the line below:<\/p>\n<pre class=\"csharpcode\"><span class=\"kwrd\">&lt;<\/span><span class=\"html\">SingleSignOnService<\/span> \r\n<span class=\"attr\">  Location<\/span><span class=\"kwrd\">=\"https:\/\/accounts.accesscontrol.windows.net\/929bfe53-8d2d-4d9e-a94d-dd3c121183b4\/v2\/saml2\"<\/span> \r\n<span class=\"attr\">  Binding<\/span><span class=\"kwrd\">=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\"<\/span><span class=\"kwrd\">\/&gt;<\/span><\/pre>\n<p>&nbsp;<\/p>\n<style type=\"text\/css\"><!--\n.csharpcode, .csharpcode pre\n{\n\tfont-size: small;\n\tcolor: black;\n\tfont-family: consolas, \"Courier New\", courier, monospace;\n\tbackground-color: #ffffff;\n\t\/*white-space: pre;*\/\n}\n.csharpcode pre { margin: 0em; }\n.csharpcode .rem { color: #008000; }\n.csharpcode .kwrd { color: #0000ff; }\n.csharpcode .str { color: #006080; }\n.csharpcode .op { color: #0000c0; }\n.csharpcode .preproc { color: #cc6633; }\n.csharpcode .asp { background-color: #ffff00; }\n.csharpcode .html { color: #800000; }\n.csharpcode .attr { color: #ff0000; }\n.csharpcode .alt \n{\n\tbackground-color: #f4f4f4;\n\twidth: 100%;\n\tmargin: 0em;\n}\n.csharpcode .lnum { color: #606060; }\n--><\/style>\n<p>That line is saying that if you want to sign on in your app using SAML, you should use the endpoint specified at location (yes, it\u2019s a URL) and you should obey to the SAML binding HTTP-Redirect. A binding type is clearly an abstract concept, something that lives in our heads but has no network manifestation. Also, the form used here (URN-based, more about that below) takes all ambiguity out given that it does not even look as something that would work in a browser.<\/p>\n<p>Entry #2 is also from the metadata doc, and is also about a very abstract concept: it indicates the signature algorithm that the STS described by the metadata will use for singing the tokens it issues. Interestingly enough, this does look like an URL; and if you paste it in a browser you don\u2019t get an error! However, you don\u2019t get the resource either; you are presented with some documentation and contextual information about the spec where this particular URI is defined. So, still not a location.<\/p>\n<p>Entry #3 represents the Name claim type. Once again, it is an abstract concept (an attribute type) which is not locatable in itself. The STS uses this identifier in its metadata and in the tokens it issues to indicate that a given element should be interpreted as the subject\u2019s name.<\/p>\n<p>Entry #4 represents the identifier of the STS itself: it is the value in the token that indicates the issuer that originated it. Applications validating incoming tokens will verify that this value corresponds to the identifier of the issuer they trust. As for all the other URIs, that\u2019s not network addressable (though the use of \u201chttps\u201d is a bit unfortunate IMHO, given that it suggests a transport feature that is totally not relevant here).<br \/>\nHere there\u2019s an interesting observation: the issuer URI remains the same regardless of which protocol is used for obtaining a token, while there are as many issuer URLs as there are supported protocols.<\/p>\n<p>Entry #5 starts to get more interesting. That URI is what I have used to indicate the realm of the Web application I described in <a href=\"https:\/\/www.cloudidentity.com\/blog\/2013\/01\/09\/using-the-jwt-handler-for-implementing-poor-mans-delegationactas-4\/\">this post<\/a>. The function of the realm in authentication protocols is to indicate to the STS the identity of the application for which a token is being requested. Furthermore, it is used by the STS to scope the tokens it issue to the application: by including the app identifier back in the token (does AudienceRestriction ring a bell?) it guarantees that the token cannot be reused against another app on a different realm. Long story short, that is an absolutely necessary piece of information, without which the SSO flow cannot take place: which leads me to the confusing part.<br \/>\nFor usability reasons, development stacks don\u2019t force you to enter a realm; they usually pick a reasonable default, so that you can click-click-click and F5. The most common default value for the realm is\u2026 the URL of the Web project you are developing. It is a good default choice, but unfortunately it created such a tight correlation between two different concepts\u00a0 &#8211; the URL at which the application is hosted and the URI identifying the app \u2013 that now a lot of people think that they are one and the same. By now you know that they really aren\u2019t.<br \/>\nThere is another reason for which it is convenient to think about the realm as an identifier. The boundaries of your applications\/solutions are not necessarily defined by the application artifact per se, you decide if the security realm is limited to your frontend or if it includes other apps or tiers. Using the URL of one of the artifacts in your solution would make it awkward to access the other components, given that the resulting token would be seemingly scoped to the wrong granularity. Don\u2019t worry too much if this last part is not too clear, it is not strictly required for getting the more general point here: however if you want to know more see <a href=\"https:\/\/www.cloudidentity.com\/blog\/2013\/01\/09\/using-the-jwt-handler-for-implementing-poor-mans-delegationactas-4\/\">this<\/a>.<\/p>\n<p>I saved the most philosophical case last. #6 represents the realm of one Web app targeting Windows Azure Web Sites. Interestingly, that looks exactly like the last URL in the first list; but in this case, it plays a completely different role; it identifies the app rather than providing its location. Want proof? Here there\u2019s a mental experiment. Think of the moment in which I create the Visual Studio project for the application. At first, the app will be created on IIS express and will have a URL of the form <a href=\"http:\/\/localhost:34534\">http:\/\/localhost:34534<\/a> or similar. Now, say that I want to set up single sign on for the app already while I am doing development (hence on IIS express); also, say that I already know that once I am done with development I will deploy this to vibro.azurewebsites.net. As part of the SSO configuration process, I can already assign \u201chttps:\/\/vibro.azurewebsites.net\u201d as a realm even if my current URL is localhost based and the network addressable endpoint for the WAWS site does not exist yet!<br \/>\nNote, as by now you know I don\u2019t *have* to use the final URL of the app as a realm; I could accept the default realm value at creation time (which would be \u201c<a href=\"http:\/\/localhost:34534\">http:\/\/localhost:34534<\/a>\u201d) and keep the same value when pushing the app in production in the cloud; however it would not be a very meaningful name, and if I\u2019d do that often I would end up with a bunch of apps in production all named localhost:something which would not be great for managing them. Having the realm value reflect something that refers to the app is simply a good naming strategy, but you could just as well apply it to urn-based URIs.<\/p>\n<p>&#8212;&#8212;&#8211;<\/p>\n<p>Still with me? Great! I believe that the above made y point, hence I could fold and go to sleep (it\u2019s 2:30am on the night between Friday and Saturday: what\u2019s wrong with me? <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-winkingsmile\" alt=\"Winking smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/03\/wlEmoticon-winkingsmile.png\" \/>) but I would just like to spend a couple of words on explaining what the heck those \u201curn:\u2026\u201d thingies are.<\/p>\n<p>All URIs (hence also all URLs) follow the same syntax:<\/p>\n<p align=\"center\"><strong><span style=\"text-decoration: underline;\">&lt;scheme&gt;:&lt;scheme-specific-part&gt;<\/span><\/strong><\/p>\n<p>You have seen the same pattern often: the head part (the scheme) gives hints to the consumer which understand that particular scheme about how to interpret the information that follows.<br \/>\nNow, the above is not especially prescriptive. For URLs, the scheme is often a protocol which will provide its own guidance about how to work with the scheme-specific-parts. To provide some normative guidance for names as well, the RCF described a URI based naming schema (<a href=\"http:\/\/tools.ietf.org\/html\/rfc2141\">URN<\/a>) which is what I used in the various examples beginning with \u201curn:\u201d.<\/p>\n<p>&nbsp;<\/p>\n<p>Thank you for having read all the way to here, hats off for your stamina <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" alt=\"Smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/03\/wlEmoticon-smile.png\" \/>!<br \/>\nIf you have questions about this URI!=URL thing, or you think parts of this post are confusing, please leave a comment: I really really want to make sure that this is as crisp as it can get <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" alt=\"Smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/03\/wlEmoticon-smile.png\" \/><\/p>\n","protected":false},"excerpt":{"rendered":"<p>[does this sound like common sense to you? Fantastic, please skip this post in its entirety. But lately I am stumbling in people confused about this every day, hence I going to write a post and start pointing them here] Let me get this straight right away: \u201cURL\u201d and \u201cURI\u201d are NOT interchangeable&#8230;<\/p>\n","protected":false},"author":1,"featured_media":1523,"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-1519","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\/1519","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=1519"}],"version-history":[{"count":2,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/1519\/revisions"}],"predecessor-version":[{"id":1525,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/1519\/revisions\/1525"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media\/1523"}],"wp:attachment":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media?parent=1519"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/categories?post=1519"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/tags?post=1519"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}