<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Neil Madden</title>
    <description>The latest articles on Forem by Neil Madden (@neilmadden).</description>
    <link>https://forem.com/neilmadden</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1831%2Fneilmadden.jpg</url>
      <title>Forem: Neil Madden</title>
      <link>https://forem.com/neilmadden</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/neilmadden"/>
    <language>en</language>
    <item>
      <title>XSS doesn’t have to be game over</title>
      <dc:creator>Neil Madden</dc:creator>
      <pubDate>Thu, 10 Dec 2020 13:01:46 +0000</pubDate>
      <link>https://forem.com/neilmadden/xss-doesn-t-have-to-be-game-over-5d3h</link>
      <guid>https://forem.com/neilmadden/xss-doesn-t-have-to-be-game-over-5d3h</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UfdUxuuh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://neilmadden.files.wordpress.com/2020/12/img_4125.png%3Fw%3D854" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UfdUxuuh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://neilmadden.files.wordpress.com/2020/12/img_4125.png%3Fw%3D854" alt=""&gt;&lt;/a&gt;A message I’m very used to seeing – but does XSS have to mean game over for web security?&lt;/p&gt;

&lt;p&gt;There’s a persistent belief among web security people that &lt;a href="https://portswigger.net/web-security/cross-site-scripting"&gt;cross-site scripting (XSS)&lt;/a&gt; is a “game over” event for defence: there is no effective way to recover if an attacker can inject code into your site. &lt;a href="https://mailarchive.ietf.org/arch/msg/oauth/M2mc6BaHQyeOHajUVpVrAREr9nk/"&gt;Brian Campbell refers to this&lt;/a&gt; as “XSS Nihilism”, which is a great description. But is this bleak assessment actually true? For the most part yes, but in this post I want to talk about a faint glimmer on the horizon that might just be a ray of sunshine after all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is XSS so catastrophic anyway?
&lt;/h2&gt;

&lt;p&gt;A naïve view of the dangers of XSS is that the attacker primarily wants to steal your authentication tokens or cookies so that they can use them from their own machine to perform malicious actions in their own time. This used to be a very common attack pattern, but it has a lot of drawbacks for the attacker:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is easily defeated by simple measures such as using &lt;a href="https://blog.codinghorror.com/protecting-your-cookies-httponly/"&gt;HttpOnly cookies&lt;/a&gt;, which stop the attacker’s script being able to steal your session cookie in the first place.&lt;/li&gt;
&lt;li&gt;If the web app in question is only accessible from a corporate network or VPN, then the attacker won’t be able to connect to it from their own machine even if they have your cookie.&lt;/li&gt;
&lt;li&gt;By using their own machine (or a compromised machine they have access to already) they make it easier to detect the attack and block their access. There will be clues given away by the change of IP address, geo-location, browser version, and so on. This is by no means guaranteed, but it certainly increases the risk of the attacker being spotted.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Attackers are well aware of these issues and have developed a solution to all of them. Rather than stealing your session cookie and using it from their own machine, they will instead use the XSS attack to &lt;a href="https://beefproject.com"&gt;proxy their requests through your web browser&lt;/a&gt;. This is similar to how a &lt;a href="https://owasp.org/www-community/attacks/csrf"&gt;Cross-Site Request Forgery (CSRF) attack&lt;/a&gt; occurs, but with XSS the requests come from the &lt;em&gt;same site&lt;/em&gt; (same origin) as legitimate requests and so almost all CSRF defences can be bypassed, as shown in the image below from &lt;a href="https://livebook.manning.com/book/api-security-in-action/chapter-5/v-11/181"&gt;chapter 5 of my book&lt;/a&gt;. &lt;a href="https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#samesite-cookie-attribute"&gt;SameSite cookies&lt;/a&gt; do not protect against this attack, and nor do &lt;a href="https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#synchronizer-token-pattern"&gt;typical anti-CSRF tokens&lt;/a&gt; because the attacker’s script running in the same origin as the legitimate code can extract these from the DOM or local storage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://neilmadden.files.wordpress.com/2020/12/ch05_fig5.6_xss_proxying.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SpT6PF55--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://neilmadden.files.wordpress.com/2020/12/ch05_fig5.6_xss_proxying.png%3Fw%3D911" alt=""&gt;&lt;/a&gt;An attacker can use an XSS vulnerability to proxy their requests through the victim’s web browser. The browser will add the victim’s cookies to those requests and they will appear to be legitimate requests from the user.&lt;/p&gt;

&lt;p&gt;This technique of proxying requests through the victim’s browser can even defeat more advanced protection measures such as the in-development &lt;a href="https://tools.ietf.org/html/draft-fett-oauth-dpop-04"&gt;DPoP method&lt;/a&gt; for securing OAuth tokens against token theft or misuse. There are various advanced tricks you can try, such as using a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers"&gt;Web Worker&lt;/a&gt; to control access to tokens and keys, but that is only a partial defence as handily &lt;a href="https://mailarchive.ietf.org/arch/msg/oauth/kH3tyrjz18d1yL3PUxjDmn8Ic20/"&gt;summarised by Philippe De Ryck in this post to the OAuth mailing list&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is why web security experts are often so gloomy about XSS and describe it as Game Over. This is especially distressing given that XSS is still one of the most prevalent vulnerabilities in web applications, with &lt;a href="https://owasp.org/www-project-top-ten/2017/A7_2017-Cross-Site_Scripting_(XSS)"&gt;OWASP claiming that around two-thirds of applications have an XSS vulnerability&lt;/a&gt;. Although better JavaScript frameworks and technologies such as &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP"&gt;CSP&lt;/a&gt; and &lt;a href="https://web.dev/trusted-types/"&gt;Trusted Types&lt;/a&gt; should reduce this over time, it seems likely that we’ll have to deal with XSS for a long time to come, so it would be nice if things weren’t quite so bleak.&lt;/p&gt;

&lt;h2&gt;
  
  
  One bad solution
&lt;/h2&gt;

&lt;p&gt;Thankfully, there are some possible solutions. One quite poor solution would be to simply confirm each request with the user before allowing it to proceed. After all, if we can’t distinguish between legitimate actions performed by a user and malicious ones injected by the attacker, why not simply ask the user? “Do you really want to email all your photos to &lt;a href="mailto:hacker@example.com"&gt;hacker@example.com&lt;/a&gt;?” This assumes that the application has access to some kind of &lt;em&gt;trusted UI&lt;/em&gt; which it can use to confirm requests with the user, and which can’t be interfered with by the attacker. An example would be to send a &lt;a href="https://dev.to/neilmadden/macaroon-access-tokens-for-oauth-part-2-transactional-auth-2i9k"&gt;push authorization request&lt;/a&gt; to an app on the user’s phone, asking them to confirm each request.&lt;/p&gt;

&lt;p&gt;This kind of solution can work for occasional high-value transactions, and is often used in banking for exactly that use-case. But it’s not a general solution that could be used for &lt;em&gt;every&lt;/em&gt; request made by your app. Users would quickly get tired of manually approving requests every time they click on a link or added an item to their shopping cart. Anyone who’s ever installed &lt;a href="https://www.obdev.at/products/littlesnitch/index.html"&gt;Little Snitch&lt;/a&gt; will know this feeling. Also many legitimate requests made by an app are not made in direct response to a user action or are not meaningful to users, so it would be hard for them to even know whether it was something they wanted to do or not.&lt;/p&gt;

&lt;p&gt;So this specific solution is not very practical, but it does illustrate that solutions are possible: XSS is not &lt;em&gt;necessarily&lt;/em&gt; Game Over. But it probably is within the mental models we’re used to using to think about web security.&lt;/p&gt;

&lt;h2&gt;
  
  
  A ray of sunlight
&lt;/h2&gt;

&lt;p&gt;If we can’t ask the user to confirm every request, is there another way that we can distinguish between legitimate and malicious requests that can’t be easily defeated? The key is to notice that proxying requests through a web browser is an example of a &lt;a href="https://en.wikipedia.org/wiki/Confused_deputy_problem"&gt;Confused Deputy attack&lt;/a&gt;, just like CSRF. The attacker instructs the web browser (or JavaScript app) to make requests of their choosing, and the browser/app happily adds the user’s authority to those requests in the form of a cookie, access token, DPoP proof, or whatever. This type of attack can only occur because an attacker is able to construct a valid request independently of having the authority to perform it, and can then trick another person/process (the “deputy”) to perform it for them.&lt;/p&gt;

&lt;p&gt;A systematic solution to confused deputy problems is provided by &lt;em&gt;capability security&lt;/em&gt;, which I discuss in some detail &lt;a href="https://livebook.manning.com/book/api-security-in-action/chapter-9/v-11/9"&gt;in chapter 9 of my book&lt;/a&gt; and also in an &lt;a href="https://dev.to/neilmadden/can-you-ever-safely-include-credentials-in-a-url-55c8-temp-slug-7809979"&gt;older post on this blog&lt;/a&gt;. A fundamental principle of capability security is to &lt;em&gt;&lt;a href="https://srl.cs.jhu.edu/pubs/SRL2003-02.pdf"&gt;combine designation with authority&lt;/a&gt;&lt;/em&gt;: it shouldn’t be possible even name a resource that you don’t have access to, much less craft a legitimate request to access it. For a web application, the idea is that rather than having a single cookie or token that provides access to everything, you would instead have lots of individual tokens that provide access to specific objects—one particular photo, for example—and that you encode these individual tokens directly into the URLs that are used to access these objects. The only way to have a legitimate URL is to be given one, and it’s impossible for any user to create one from scratch. (In the book I go into more detail about how to make this secure and &lt;a href="https://restfulapi.net/hateoas/"&gt;convenient&lt;/a&gt;, which I won’t repeat here).&lt;/p&gt;

&lt;p&gt;If access to a website was driven by capability URLs rather than cookies or all-powerful access tokens, then the attacker’s job after exploiting an XSS vulnerability is much harder. They cannot simply proxy requests through the victim’s web browser because, without access to any capability URLs, they cannot even begin to create those requests. Instead they must try to steal capability URLs from the app or intercept them in use, and hope that the ones they capture correspond to objects they want to access or manipulate. By storing capability URLs inside &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures"&gt;closures&lt;/a&gt; or using other &lt;a href="https://medium.com/agoric/ses-securing-javascript-in-the-real-world-4f309e6b66a6"&gt;security boundaries&lt;/a&gt;, an app can make it very hard for an attacker to intercept these URLs. I also believe that browser vendors could provide further protection by supporting a special URL scheme for capability URLs, but I’ll write about that another time.&lt;/p&gt;

&lt;p&gt;I believe that such an approach can be made very secure against XSS attacks, while also being immune to CSRF attacks. But it’s very different to how most web apps are written today, and would require a fundamental change in security architecture. I have some ideas about how future versions of OAuth could incorporate some of these ideas, and with a bit of work you could retrofit it using techniques such as &lt;a href="https://dev.to/neilmadden/least-privilege-with-less-effort-macaroon-access-tokens-for-oauth-4g3o"&gt;macaroons&lt;/a&gt; to create many individual tokens from a single all-powerful one (and then throw that one away). I believe that the security advantages are worth it, and I further believe that a capability-security model is the only viable long-term approach for securing the web. The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy"&gt;same-origin policy&lt;/a&gt; has never been very effective, as the continued impact of XSS shows, and things like CSP and SameSite cookies are at best a poorly-fitting sticking plaster. At some point we need to rip it off and adopt a more systematic approach.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Insert &lt;a href="http://waterken.sourceforge.net/web-key/"&gt;coin&lt;/a&gt; to continue playing.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>security</category>
    </item>
    <item>
      <title>Macaroon access tokens for OAuth: Part 2 – transactional auth</title>
      <dc:creator>Neil Madden</dc:creator>
      <pubDate>Wed, 09 Sep 2020 15:49:55 +0000</pubDate>
      <link>https://forem.com/neilmadden/macaroon-access-tokens-for-oauth-part-2-transactional-auth-2i9k</link>
      <guid>https://forem.com/neilmadden/macaroon-access-tokens-for-oauth-part-2-transactional-auth-2i9k</guid>
      <description>&lt;p&gt;In &lt;a href="https://dev.to/neilmadden/least-privilege-with-less-effort-macaroon-access-tokens-for-oauth-4g3o"&gt;part 1&lt;/a&gt;, I showed how &lt;a href="https://backstage.forgerock.com/docs/am/7/oauth2-guide/oauth2-macaroons.html"&gt;Macaroon access tokens in ForgeRock Access Management 7.0&lt;/a&gt; can be used as a lightweight and easy-to-deploy alternative to proof of possession (PoP) schemes for securing tokens in browser-based apps. The same techniques can be adapted to secure tokens in microservice architectures and IoT applications, and I hope to expand on some of the patterns they enable in future blog posts. But in this post, I want to look at &lt;em&gt;third-party caveats&lt;/em&gt; and their application to transactional authorization.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is transactional authorization?
&lt;/h2&gt;

&lt;p&gt;In a normal OAuth flow, a user is granting some part of their authority to an app or service for ongoing access. For example, you might grant an app read-only access to files in your Dropbox or Google Drive. In these cases the scope of access is usually well defined, allowing the client to easily determine what scope to ask for (eg, &lt;code&gt;read-all-files&lt;/code&gt;), and the grant of authority creates a long-lived relationship between the user and the client. If the user stops using the app, or otherwise decides to end this relationship, they can typically go to a page on the authorization server and revoke access from that client.&lt;/p&gt;

&lt;p&gt;In transactional authorization the setup is somewhat different. The paradigmatic example is of making a high-value bank transfer. Suppose you want use an independently developed app to send $500 to your friend Alice. In a normal OAuth flow you’d grant the app some static scope like &lt;code&gt;bank-transfer&lt;/code&gt;, and then it would be authorized to make any bank transfer on your behalf. But this is a bit risky, unless you really really trust that app, because it could then make lots of bank transfers that you haven’t asked for. The solution is to require authorization for each individual transfer. When you click the button to send $500 to Alice, your bank actively confirms this with you outside of the app to make sure that you really intended it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pixabay.com/illustrations/money-transfer-mobile-banking-3588301/"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Qma06n1P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://neilmadden.files.wordpress.com/2020/09/money-transfer-3588301_640.jpg%3Fw%3D640" alt="Illustration of money being transferred using a mobile app."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this to work, the user needs to be told the details of the transaction she is approving: how much money is being transferred, from which account, and to who? It seems intuitive that you could use OAuth to approve these individual transactions. Unfortunately, OAuth is not very good at details. The set of scopes understood by an authorization server is usually fixed and independent of any particular request, so there is no easy way to encode the specific details of a transaction. To get around this, the real &lt;a href="https://standards.openbanking.org.uk"&gt;Open Banking specifications&lt;/a&gt; (in the UK at least) require that the payment details are registered with the bank first to obtain a ConsentId that is then included in the OAuth authorization request by (ab)using the &lt;a href="https://openid.net/specs/openid-connect-core-1_0.html#IndividualClaimsRequests"&gt;OpenID Connect claims parameter&lt;/a&gt;. My employer, ForgeRock, have a good &lt;a href="https://www.forgerock.com/industries/financial-services/open-banking/UK-Spec#nb-3req-consent"&gt;explainer of this process.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is all a little awkward, so there are proposals to add native &lt;a href="https://tools.ietf.org/html/draft-ietf-oauth-rar-02"&gt;support for transactions to OAuth 2&lt;/a&gt;, or to develop a &lt;a href="https://oauth.xyz"&gt;new protocol&lt;/a&gt; that supports this from the start (&lt;a href="https://datatracker.ietf.org/wg/gnap/documents/"&gt;gnow a separate IETF working group&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Macaroons and transactions
&lt;/h2&gt;

&lt;p&gt;You may wonder how macaroons fit into all of this, seeing as this is a post about macaroons. Well, it turns out that they are a very good fit for transactional authorization, due to something known as &lt;em&gt;third-party caveats&lt;/em&gt;. I’ll get to what those are in a moment, but first let’s consider some aspects of using OAuth for this. Suppose you had an OAuth provider that let you send a richly structured description of the transaction instead of a simple scope string. This is what the &lt;a href="https://tools.ietf.org/html/draft-ietf-oauth-rar-02"&gt;Rich Authorization Requests (RAR) proposal&lt;/a&gt; for OAuth 2 allows. The process would look something like the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To initiate a payment, the client (app) would send an authorization request to the authorization server (bank) with the details of the transfer. &lt;/li&gt;
&lt;li&gt;The bank would then authenticate the user and ask for consent to approve this specific transaction. &lt;/li&gt;
&lt;li&gt;If approved, the client would get back an access token with the scope being the details of the transaction.&lt;/li&gt;
&lt;li&gt;The client uses the access token to call an API on the bank to actually perform the transfer. As part of this, the bank would check that the approved detailed scope matches the actual transfer being requested.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In principle this all works fine, but it lacks some safeguards. Every transaction is effectively a brand new interaction with the client and the access grant is only valid for that one specific transaction. This &lt;a href="https://mailarchive.ietf.org/arch/msg/oauth/CRumN2jZTYocZKu_0ur5DSsg4Qo/"&gt;has some negative consequences&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There is no permanent relationship between the user and the client app stored at the AS. This means that if the user uninstalls the app or otherwise decides she no longer wants to use it, there is no way for her to revoke the ability for it to initiate payment consent requests.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Any&lt;/em&gt; registered client with the bank can suddenly decide to initiate a payment, even if I have no pre-existing relationship with them. As the continued success of phishing attacks shows, if you can pop up a consent screen on a user’s device then the battle is half won. In a highly regulated ecosystem like Open Banking you can perhaps rely on legal controls to prevent clients acting unethically, but as a user I’d prefer that only clients that &lt;em&gt;I&lt;/em&gt; have explicitly approved can ask me to initiate transactions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can read more detailed discussion of these issues &lt;a href="https://mailarchive.ietf.org/arch/msg/oauth/CRumN2jZTYocZKu_0ur5DSsg4Qo/"&gt;in the email thread&lt;/a&gt; I linked above. Not everyone agrees with my position, so make your own mind up.&lt;/p&gt;

&lt;p&gt;We can use macaroon access tokens to overcome these issues. The basic idea is that the user would approve a long-lived access token (and optional refresh token) when she first installs an app or signs up for a service. This access token would have a normal static OAuth scope like &lt;code&gt;initiate_payments&lt;/code&gt;. Then individual transfers can be authorized by appending a caveat that ties the token to a specific transaction, either by referencing a unique transaction ID (like the ConsentId of Open Banking) or directly including the structured transaction details in the caveat. This provides the best of both worlds. The user has a single long-lived authorization grant with the client, which she can revoke whenever she wants, and we can derive unique per-transaction tokens from that to approve individual requests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Third-party caveats
&lt;/h2&gt;

&lt;p&gt;The major downside of the scheme I just described is that the client can just approve its own transactions by appending a suitable caveat to its access token. No need to involve the user at all! What we want is some kind of caveat attached to the access token that forces the client to obtain authorization from the user for each transaction. This is exactly what macaroon third-party caveats allow.&lt;/p&gt;

&lt;p&gt;The caveats we saw in &lt;a href="https://dev.to/neilmadden/least-privilege-with-less-effort-macaroon-access-tokens-in-am-7-0-412f-temp-slug-469202"&gt;part 1&lt;/a&gt;are all examples of &lt;em&gt;first-party caveats&lt;/em&gt;: simple restrictions on how a token can be used that can be checked at the point of use (by the resource server). A &lt;em&gt;third-party caveat&lt;/em&gt; can’t be checked locally by the RS, but instead requires the client to visit another service (the third party) and obtain proof that it satisfies some condition. For example, you might have an access token that allows placing orders for alcohol, but only if the client gets a proof from a government service that the user is over 18. The proof is in the form of a &lt;em&gt;discharge macaroon&lt;/em&gt; that is cryptographically tied to the original caveat. The client presents the original macaroon and the discharge macaroon to the API to gain access.&lt;/p&gt;

&lt;p&gt;(A cool feature is that discharge macaroons can themselves contain caveats, including more third-party caveats, requiring the client to get more proofs before they can access a protected resource).&lt;/p&gt;

&lt;p&gt;We can use this property of third-party caveats to implement transactional authorization. The original long-lived access token issued to the client will contain a third-party caveat that requires the client to obtain a discharge macaroon from a separate &lt;em&gt;transaction authorization service&lt;/em&gt; in order to initiate a payment. This transaction authorization service will authenticate the user and approve the transaction and then issue a discharge macaroon that approves that one transaction (by adding appropriate first-party caveats to bind it to the transaction ID or details). The client then presents its original long-lived access token and the discharge macaroon to a payment service to action the transfer.&lt;/p&gt;

&lt;p&gt;This has some very nice properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The user gets to manage their relationship with the client over time exactly as they would for any other OAuth client.&lt;/li&gt;
&lt;li&gt;The &lt;em&gt;permission to ask to initiate transactions&lt;/em&gt; is itself properly represented as a separate scope that the user can consent to in an informed manner, rather than just letting any client initiate transactions.&lt;/li&gt;
&lt;li&gt;Discharge macaroons are completely stateless and so consume no resources on the authorization server.&lt;/li&gt;
&lt;li&gt;The AS need not be involved in individual transaction authorizations, which is nice if you are outsourcing the AS to a cloud service but don’t want them tracking individual user activity at that fine grained level. (Although you could use features of the AS if you wished, such as &lt;a href="https://backstage.forgerock.com/docs/am/7/authorization-guide/transactional-authorization.html"&gt;ForgeRock’s rich existing support for transactional authorization&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3rd-party caveats in AM 7.0
&lt;/h2&gt;

&lt;p&gt;An idea is one thing, but it would be nice if you could actually implement this. Well, we thought so too, so we built some experimental support for 3rd-party caveats into AM 7.0 alongside the macaroon access token support I described in part 1.&lt;/p&gt;

&lt;p&gt;Adding the 3rd-party caveat is simple using AM’s support for &lt;a href="https://backstage.forgerock.com/docs/am/7/oauth2-guide/modifying-access-tokens-scripts.html"&gt;access token modification scripts&lt;/a&gt;. This allows an administrator to configure a JavaScript or Groovy script to make modifications to access tokens before they are issued. If you turn on macaroon access tokens then you can also add caveats to an access token as shown in the screenshot below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X7S_Edh6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://neilmadden.files.wordpress.com/2020/09/screenshot-2020-09-09-at-16.01.40.png%3Fw%3D1024" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X7S_Edh6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://neilmadden.files.wordpress.com/2020/09/screenshot-2020-09-09-at-16.01.40.png%3Fw%3D1024" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this example, we’re adding a third-party caveat to the access token to force the client to go to the transactional authorization service at &lt;code&gt;https://txauth.example&lt;/code&gt; whenever it wants to use the access token. The third-party caveat consists of three parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A hint for where the client has to go to obtain a discharge macaroon&lt;/li&gt;
&lt;li&gt;A unique random secret key that will be used to sign the discharge macaroon (known as the &lt;em&gt;caveat key&lt;/em&gt;). This gets encrypted and encoded into the macaroon so that only the verifier can recover it.&lt;/li&gt;
&lt;li&gt;An identifier to give to the third party service so that it knows what condition needs to be checked and how to recover the caveat key. In this example, I’ve encrypted the caveat key using a shared secret between the AS and the transactional authorization service, but you could also use public key encryption or pre-register the caveat key with the service and include a unique identifier instead.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once the 3rd-party caveat is attached, the access token will be considered invalid unless it is accompanied by a discharge macaroon signed with the caveat key. The transaction authorization service can easily create the discharge macaroon using a macaroon library, as shown in this example code I wrote to test the idea using our internal macaroon library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Parse the macaroon access token and find the 3rd-party caveat // that requires authorizationMacaroon accessTokenMacaroon = Macaroon.deserialize(accessToken);Caveat txCaveat = accessTokenMacaroon.getThirdPartyCaveats() .filter(caveat -&amp;gt; SELF.equals(caveat.getLocationHint())) .findAny() .orElseThrow(() -&amp;gt; new IllegalArgumentException());// The key to create the discharge macaroon is encrypted in the 3rd-party // caveat, so decrypt it with the shared secret to recover it.Key caveatKey = decryptCaveatKey(txCaveat);// Now generate a discharge macaroon that satisfies the 3rd-party caveat.// We add additional caveats to this discharge macaroon that tie it to // this specific transaction and limiting the time it can be used for. String dischargeMacaroon = Macaroon.create(caveatKey, SELF, txCaveat.getIdentifier()) .addFirstPartyCaveat(new JsonCaveatSet() .expiresAt(now().plus(1, MINUTES)) .audience("https://payments.bank.example.com") .put("tx", json.toMap())) .serialize();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To verify the 3rd-party caveat has been satisfied, we added a new (non-standard!) header to the OAuth introspection endpoint that allows passing the discharge macaroon: &lt;code&gt;X-Discharge-Macaroon&lt;/code&gt;. This is a header rather than a body parameter partly to give a hint that this is a non-standard extension and partly because there may be multiple discharge macaroons, but introspection request parameters can’t be repeated.&lt;/p&gt;

&lt;p&gt;In the spirit of making this as transparent as possible for the RS (apart from the extra header of course), the introspection response combines the caveats of the original access token and any attached to the discharge macaroon. For example, if the discharge macaroon has an earlier expiry time than the access token then this will be reflected in the expiry time in the response. The same occurs for scope and audience restrictions on the discharge macaroon, making it easy for the transaction authorization service to limit what that client can do in the context of this one specific transaction.&lt;/p&gt;

&lt;p&gt;Any unrecognized caveats are returned in a new “caveats” element on the introspection response, allowing the transaction details associated with the discharge macaroon to be returned:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{ "active": true", ... "caveats": { "tx": { "type": "payment\_initiation", "locations": ["https://example.com/payments"], "instructedAmount": { "currency": "EUR", "amount": "123.50" }, "creditorName": "Merchant123", "creditorAccount": { "iban": "DE02100100109307118603" }, ... }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The payment service can then check these details match the transaction being processed (for example, using the scripting features of ForgeRock Identity Gateway 7.0 which support extracting and checking individual fields in the introspection response). Importantly, the use of the introspection endpoint ensures that the access token signing key never has to leave the AS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In my opinion, third-party caveats present a really interesting alternative way of thinking about transactional authorization in OAuth. They have a lot of advantages compared to other approaches, and you can put together a working solution with very little code. It took me less than 2 hours to prototype a fully working version of the solution presented here using the existing features of AM I’d already added, before I’d even considered that they might be useful for transactional authZ. To me this is one of the real benefits of macaroon access tokens: they enable an extraordinary level of flexibility in the solution design space.&lt;/p&gt;

&lt;p&gt;I’m sure there are plenty of downsides to this approach too. It relies pretty heavily on token introspection, which isn’t always a suitable solution. It also requires the RS to handle two (or more) tokens rather than just a single one. (Perhaps it would be better to “staple” them together?) The support for 3rd-party caveats in AM 7.0 is most definitely &lt;em&gt;experimental&lt;/em&gt;, but I believe it points the way to some really interesting future capabilities. I’d love to hear feedback on this feature, and I’d love to eventually move towards standardisation of macaroon access tokens for OAuth. Let me know what you think in the comments.&lt;/p&gt;

&lt;p&gt;PS – I’ll try and publish the demo code I have so that you can try it out if anyone is interested.&lt;/p&gt;

</description>
      <category>macaroons</category>
      <category>oauth</category>
      <category>authorization</category>
    </item>
    <item>
      <title>Least privilege with less effort: Macaroon access tokens for OAuth</title>
      <dc:creator>Neil Madden</dc:creator>
      <pubDate>Wed, 29 Jul 2020 17:20:58 +0000</pubDate>
      <link>https://forem.com/neilmadden/least-privilege-with-less-effort-macaroon-access-tokens-for-oauth-4g3o</link>
      <guid>https://forem.com/neilmadden/least-privilege-with-less-effort-macaroon-access-tokens-for-oauth-4g3o</guid>
      <description>&lt;h2&gt;
  
  
  Part 1: Lightweight PoP
&lt;/h2&gt;

&lt;p&gt;One of the major changes between OAuth 1 and OAuth 2 was the decision to drop the requirement that &lt;a href="https://oauth.net/core/1.0a/#signing_process"&gt;requests had to be signed&lt;/a&gt; using a secret key associated with each access token. This signing process was notoriously hard to get right and dropping it from OAuth 2 enormously simplified the life of client and resource server developers. In OAuth 2, access tokens are pure bearer tokens, a bit like passwords: if you know the value of the token you can use it, without needing any other credentials. This is very easy for developers, but is definitely less secure. The rise of single-page apps (SPAs) and other browser-based clients leaves access tokens more exposed to theft or accidental leakage compared to traditional server-side clients.&lt;/p&gt;

&lt;h2&gt;
  
  
  Drinking the PoP
&lt;/h2&gt;

&lt;p&gt;Signed requests in OAuth 1 are an example of proof-of-possession (PoP) tokens rather than bearer tokens. If bearer tokens are like cash, PoP tokens are like &lt;a href="https://en.wikipedia.org/wiki/EMV"&gt;Chip-and-PIN&lt;/a&gt;. Even if you steal an OAuth 1 token you can’t use it without the associated secret key used to sign requests. The only problem was it turned out that even if you did have the secret key you often couldn’t use the token either, because it was just too hard to get request signing to work reliably. Some brave souls periodically try and revive this idea.&lt;/p&gt;

&lt;p&gt;To get around the problems with request signing, various alternative schemes have been proposed. Brian Campbell gave a nice overview of the history of OAuth PoP schemes at Identiverse recently, called &lt;a href="https://onlinexperiences.com/Launch/Event/ShowKey=96547"&gt;The Burden of Proof&lt;/a&gt;. It’s a good talk and worth watching. The latest such scheme is &lt;a href="https://tools.ietf.org/html/draft-fett-oauth-dpop-04"&gt;DPoP&lt;/a&gt;, which tries to keep things as simple as possible: rather than signing the whole request, you just sign enough basic details of the request (the URI and HTTP method) to be able to stop the most likely attacks and rely on TLS to protect the content of the request.&lt;/p&gt;

&lt;p&gt;DPoP is good, and for some use-cases I think it’s really good, but it still has some downsides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Although the signature process itself is simplified, the client still has to generate and manage this secret key securely, which adds complexity that many client developers will avoid unless they have to.&lt;/li&gt;
&lt;li&gt;The client, authorization server, and resource servers all have to know about DPoP. It’s quite hard to incrementally deploy.&lt;/li&gt;
&lt;li&gt;It relies on fresh public key signatures on every request. Public key crypto is slow and expensive, so you generally want to do it as little as possible. I could imagine a rollout of DPoP requiring a significant increase in front-line servers to handle the extra load.&lt;/li&gt;
&lt;li&gt;DPoP is based on JWS, which supports &lt;a href="https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-algorithms"&gt;a wide range of signature algorithms&lt;/a&gt;, with no guidance as to which one to use. This means the resource servers have to potentially support them all (including some really expensive ones like ES512), or risk rejecting some clients. Clients will also have to guess which algorithms the server supports when they generate the private key. In practice this means that DPoP will only be used in closed deployments, or else everyone will gravitate to a lowest common denominator option like 2048-bit RSA with PKCS#1 v1.5 padding.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mailarchive.ietf.org/arch/msg/openpgp/5rnE9ZRN1AokBVj3VqblGlP63QE/"&gt;Public&lt;/a&gt; &lt;a href="https://en.wikipedia.org/wiki/ROCA_vulnerability"&gt;key&lt;/a&gt; &lt;a href="https://www.bleepingcomputer.com/news/security/some-yubikey-fips-keys-allow-attackers-to-reconstruct-private-keys/"&gt;signature&lt;/a&gt; &lt;a href="https://toadstyle.org/cryptopals/62.txt"&gt;algorithms&lt;/a&gt; &lt;a href="https://medium.com/asecuritysite-when-bob-met-alice/not-playing-randomly-the-sony-ps3-and-bitcoin-crypto-hacks-c1fe92bea9bc"&gt;are&lt;/a&gt; &lt;a href="https://research.kudelskisecurity.com/2017/10/04/defeating-eddsa-with-faults/"&gt;fragile&lt;/a&gt;. The point of a signature is that it can be verified by anybody, but in the case of an OAuth request the DPoP token only needs to be verified by exactly one party: the server that you’re sending the request to. There are much simpler and safer ways to achieve request authentication in this case.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Taking the biscuit
&lt;/h2&gt;

&lt;p&gt;OK, so if DPoP is still too complex, what would a better solution look like? The risk that PoP solutions are trying to prevent is an access token being stolen from one request and used to authorize completely different requests that the client didn’t intend. A different way to solve this problem would be to have individual access tokens for every request that just authorizes that one specific request and no others. For example, it could have an audience restriction limiting it to only be used for requests to one specific server, and a single scope that authorizes just the specific type of API call that is being made. The expiry time could be limited to just a few seconds in the future, and so on. In current OAuth implementations it’s pretty hard to restrict an access token to exactly one request, but you can get pretty close.&lt;/p&gt;

&lt;p&gt;Of course, this all sounds like a nightmare. The client can’t keep going back to the user to authorize access tokens for every little request! &lt;/p&gt;

&lt;p&gt;It turns out there is a way to get lots of little access tokens for individual requests. It’s easy for developers, relatively simple to deploy, and cheap. (&lt;em&gt;Much&lt;/em&gt; cheaper than digital signatures). It’s also quite delicious.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YArfBDTq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh5.googleusercontent.com/-s1BGxwv8J2_P8JVvbMdzz_SqvLZaOnGD6jii2Gsz9adhtw-SA1H2zxod3ab-x8pkn3OaZ0UAcLJrRiMc_s4NXarrjrATJP3g8nBdZkLH-CSWeemEQ-FzTXNtIMwAtvmi_kzOhcF" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YArfBDTq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh5.googleusercontent.com/-s1BGxwv8J2_P8JVvbMdzz_SqvLZaOnGD6jii2Gsz9adhtw-SA1H2zxod3ab-x8pkn3OaZ0UAcLJrRiMc_s4NXarrjrATJP3g8nBdZkLH-CSWeemEQ-FzTXNtIMwAtvmi_kzOhcF" alt="Chocolate coated macaroons"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter macaroons
&lt;/h2&gt;

&lt;p&gt;Apart from being &lt;a href="https://en.wikipedia.org/wiki/Macaroon"&gt;a tasty treat&lt;/a&gt;, macaroons are also &lt;a href="http://evancordell.com/2015/09/27/macaroons-101-contextual-confinement.html"&gt;a new token format&lt;/a&gt; invented by the &lt;a href="https://research.google/pubs/pub41892/"&gt;boffins at Google&lt;/a&gt;. At first glance, a macaroon is an &lt;a href="https://en.wikipedia.org/wiki/Message_authentication_code"&gt;authenticated&lt;/a&gt; token a bit like a JWT using the HS256 algorithm. But the additional yummy goodness that macaroons add is the ability to add &lt;em&gt;caveats&lt;/em&gt;. A caveat is a restriction on how the token can be used. For example, you might limit the scope of a token, or reduce its expiry time. They always reduce, never expand, the authority of the token. The really cool thing is that adding a caveat gives you a &lt;em&gt;new&lt;/em&gt; token, leaving the original token unchanged. It’s also really cheap: a few microseconds typically. This means you can have a single powerful access token and then &lt;em&gt;derive&lt;/em&gt; multiple more restricted access tokens from it. This lets us have our cake and eat it (sorry, my metaphors are all over the place today): you can get a single token approved by the user but then derive individual access tokens for every single API call you make, with just the perfect amount of privilege for that one call.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hMwiBNZO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh4.googleusercontent.com/2xwnm3nJkz_vMnxvPg1JxjX-8TF4PNPOIyAa0TlvQxRDOy4hsmqDaDn0WxhoZiddSoHjTzXlDvuC7Lmfm3HuFDlmjdkZq48x2ALVQneHElnQykrWzC7VhbUcw1rKRyeZOfvADZUC" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hMwiBNZO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh4.googleusercontent.com/2xwnm3nJkz_vMnxvPg1JxjX-8TF4PNPOIyAa0TlvQxRDOy4hsmqDaDn0WxhoZiddSoHjTzXlDvuC7Lmfm3HuFDlmjdkZq48x2ALVQneHElnQykrWzC7VhbUcw1rKRyeZOfvADZUC" alt="A picture of macaroon access tokens, showing how new tokens can be derived with reduced scope, expiry, or audience."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This gives us the benefits of having lots of tiny individual access tokens for each request, but we can generate these tokens on the fly from the original token. This is what the original macaroons paper refers to as &lt;em&gt;contextual caveats&lt;/em&gt;: specific details of the context in which an API call is taking place that we add to a token to restrict its use. That way, if the token does get stolen or misused, the scope of what you can do with it is severely limited by the caveats attached to it. The genuine client still has the original access token though, so they can still do whatever they like within the scope of the original grant.&lt;/p&gt;

&lt;p&gt;If we restrict the tokens enough then they become pretty hard to misuse. We get much of the same benefits of a PoP approach but with much less complexity. Where you might have had code like the following to call an API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fetch('[https://api.example.com/v1/kittens](https://api.example.com/v1/kittens)', {
    method: 'POST',
    headers: {
        'Authorization': 'Bearer ' + token
    },
    body: JSON.stringify(kittenDetails)
});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The new macaroon-enhanced version becomes something as simple as the following with an &lt;a href="http://macaroons.io/"&gt;appropriate library&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fetch('[https://api.example.com/v1/kittens](https://api.example.com/v1/kittens)', {
    method: 'POST',
    headers: {
        'Authorization': 'Bearer ' + **token.restrict({**  
**            aud: 'api.example.com',**  
**            exp: nowPlus5Seconds(),**  
**            scope: 'upload\_cute\_kitten\_picture'**  
**        })**
    },
    body: JSON.stringify(kittenDetails)
});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Macaroon OAuth tokens in ForgeRock AM 7.0
&lt;/h2&gt;

&lt;p&gt;At &lt;a href="https://www.forgerock.com"&gt;ForgeRock&lt;/a&gt; we love OAuth and we also love macaroons. We think they make a great combination. OAuth benefits from the simple but flexible approach to &lt;em&gt;least privilege&lt;/em&gt; that macaroons enable, and macaroons benefit from the framework and tooling that exists around OAuth. I strongly believe that macaroons provide about 90% of the benefit of PoP for about 20% of the effort.&lt;/p&gt;

&lt;p&gt;That’s why we’ve included support for issuing OAuth access and refresh tokens as macaroons in the upcoming 7.0 release of ForgeRock Access Management. So how does it work? Well, mostly you just go into the OAuth2 Provider Settings and turn it on:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GJi8qqQi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh6.googleusercontent.com/-U18sgnh544URwiVYtsEi00sqXjUX687yHwjEeey_ZYdOo49IZ63q-3STz56aBYO6pbyD5uNP_gLO4vLDUtnJA15qQuDWvPLSdaPQOqg1IGzIlW_zGvOiAwMN85fkJn7l46QMAO1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GJi8qqQi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh6.googleusercontent.com/-U18sgnh544URwiVYtsEi00sqXjUX687yHwjEeey_ZYdOo49IZ63q-3STz56aBYO6pbyD5uNP_gLO4vLDUtnJA15qQuDWvPLSdaPQOqg1IGzIlW_zGvOiAwMN85fkJn7l46QMAO1" alt='Image of toggle button to turn on "Use Macaroon Access and Refresh Tokens"'&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now when you complete an OAuth flow you get issued with a macaroon access token and optional refresh token. They look just like normal access tokens, but are a little bit longer:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AxakXEdq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh3.googleusercontent.com/KEaxly2z3I5uc5u1U88pe4ecvHeqlevepeDntwo2K6h0cPwNXIorQAwx9kapVxRCXiSV2mVpfNgwTTIuOSDUiDhf8XuWSZFifF8HQNubsTBGIeOUBQUWFHwM4rhiXHTUwKywaxE6" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AxakXEdq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh3.googleusercontent.com/KEaxly2z3I5uc5u1U88pe4ecvHeqlevepeDntwo2K6h0cPwNXIorQAwx9kapVxRCXiSV2mVpfNgwTTIuOSDUiDhf8XuWSZFifF8HQNubsTBGIeOUBQUWFHwM4rhiXHTUwKywaxE6" alt="Screenshot of Postman showing macaroon access and refresh tokens"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can call the &lt;a href="https://tools.ietf.org/html/rfc7662"&gt;standard token introspection endpoint&lt;/a&gt; to see the details of the token, just like you could with a normal access token:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1jHfrH1K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh4.googleusercontent.com/jUopMcDkP43pzpxE2d-g5M13lC1XKd-kG-37dqXreCAELtCy3KnBxbvQrtQNYybF_vfRumeqqFjKn32JoKw8LJSuLiHXys1Rw3QoNfVJucYavPzeGDCTrSLGGM0PljGMgfgpzSyz" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1jHfrH1K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh4.googleusercontent.com/jUopMcDkP43pzpxE2d-g5M13lC1XKd-kG-37dqXreCAELtCy3KnBxbvQrtQNYybF_vfRumeqqFjKn32JoKw8LJSuLiHXys1Rw3QoNfVJucYavPzeGDCTrSLGGM0PljGMgfgpzSyz" alt="Screenshot showing JSON response from the OAuth token introspection endpoint, showing the scope and other token details."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can then add a bunch of caveats just like in the example earlier, to reduce the scope, expiry time, and audience and introspect it again to see the difference:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I82ve_IP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh4.googleusercontent.com/1pxK4QVPOxCG9H-mdFrlug1IHkrJHrMR8XlsbBR806EZxr31d_MAd_fp4Jg2FxyI7RlsNUEyPXw9rzUlzkso3024unQuEjizhmrLBLyi_ctfFDV5zaUZKgteP9XLSsTNf3t72Lz-" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I82ve_IP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh4.googleusercontent.com/1pxK4QVPOxCG9H-mdFrlug1IHkrJHrMR8XlsbBR806EZxr31d_MAd_fp4Jg2FxyI7RlsNUEyPXw9rzUlzkso3024unQuEjizhmrLBLyi_ctfFDV5zaUZKgteP9XLSsTNf3t72Lz-" alt="The updated JSON response from the introspection endpoint, showing the reduced scope, expiry, and audience due to the caveats added to the token."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Repeating the token introspection request a few seconds later, the restricted access token has expired:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JqQiwi0J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh6.googleusercontent.com/DijzuCMCxX1Wnks6lezkFCYvu9Q3BR2NlSC3WrlN-hC7gAjgJ-gbUs4WRF9JIQ6ePFsM5dbj5A-rngtGAtpbumm1z38ql9WPiIg_I48RvzRQNe94mzLSvlOHRlA3lAFK4I58xc4j" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JqQiwi0J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lh6.googleusercontent.com/DijzuCMCxX1Wnks6lezkFCYvu9Q3BR2NlSC3WrlN-hC7gAjgJ-gbUs4WRF9JIQ6ePFsM5dbj5A-rngtGAtpbumm1z38ql9WPiIg_I48RvzRQNe94mzLSvlOHRlA3lAFK4I58xc4j" alt="Screenshot showing the active: false response"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But the original access token is still valid. In fact, all the details of the original token in the database (AM’s Core Token Service) are exactly as they were when the token was first issued.&lt;/p&gt;

&lt;p&gt;Everything is handled transparently through the token introspection endpoint, making it really easy to deploy this incrementally:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In step 1, you simply turn on macaroon access tokens at the Authorization Server. So long as your resource servers are using token introspection, everything can carry on as normal. Clients and resource servers need no changes.&lt;/li&gt;
&lt;li&gt;In step 2, your clients start adding caveats to tokens using a macaroon library. Resource servers carry on introspecting the tokens, but now the introspection responses take into account the caveats on the tokens.&lt;/li&gt;
&lt;li&gt;There is no step 3.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That’s a little taster of macaroon access tokens in ForgeRock AM 7.0 and why I think they will be a game changer. &lt;em&gt;Least privilege with less effort.&lt;/em&gt; In part 2, I’ll show you some more exotic things you can do with macaroon access tokens using 3rd-party caveats.&lt;/p&gt;

</description>
      <category>oauth</category>
      <category>security</category>
      <category>authorization</category>
    </item>
    <item>
      <title>What Cache-Control headers do I need?</title>
      <dc:creator>Neil Madden</dc:creator>
      <pubDate>Tue, 19 May 2020 06:38:54 +0000</pubDate>
      <link>https://forem.com/neilmadden/what-cache-control-headers-do-i-need-131p</link>
      <guid>https://forem.com/neilmadden/what-cache-control-headers-do-i-need-131p</guid>
      <description>&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching"&gt;Understanding caching&lt;/a&gt; is an important part of web development. From a performance point of view, you don’t want a client to be downloading the same large file again and again. But from a security point of view, you don’t want sensitive data, such as users’ personal details, cached by shared web proxies and served to other users. &lt;/p&gt;

&lt;p&gt;There are many aspects to HTTP caching, but the one that’s always confused me the most is the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control"&gt;Cache-Control&lt;/a&gt; header. There are so many options! When should I use each one? Why does &lt;code&gt;no-cache&lt;/code&gt; not mean “disable caching”??!&lt;/p&gt;

&lt;p&gt;To help myself remember what all the options do I made this little flowchart. Hopefully you’ll find it useful too. If you spot an error, please &lt;a href="https://github.com/NeilMadden/cache-control-flowchart"&gt;contribute on GitHub&lt;/a&gt;. And if somebody wants to make a prettier version, please do! (Just &lt;a href="https://creativecommons.org/licenses/by/4.0/"&gt;credit me&lt;/a&gt;). &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Y1JwAJKu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0wxyx8li2tzfg6x41xy7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Y1JwAJKu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0wxyx8li2tzfg6x41xy7.png" alt="A flowchart of Cache-Control header options"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/NeilMadden/cache-control-flowchart/raw/master/cache-flowchart.pdf"&gt;PDF version&lt;/a&gt;&lt;/p&gt;

</description>
      <category>http</category>
      <category>caching</category>
      <category>flowchart</category>
    </item>
    <item>
      <title>Java KeyStores—the gory details</title>
      <dc:creator>Neil Madden</dc:creator>
      <pubDate>Sat, 18 Nov 2017 17:54:22 +0000</pubDate>
      <link>https://forem.com/neilmadden/java-keystoresthe-gory-details-dnj</link>
      <guid>https://forem.com/neilmadden/java-keystoresthe-gory-details-dnj</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on my &lt;a href="https://neilmadden.wordpress.com/2017/11/17/java-keystores-the-gory-details/"&gt;blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Java KeyStores are used to store key material and associated certificates in an encrypted and integrity protected fashion. Like all things Java, this mechanism is pluggable and so there exist a variety of different options. There are lots of articles out there that describe the different types and how you can initialise them, load keys and certificates, etc. However, there is a lack of detailed technical information about exactly how these keystores store and protect your key material. This post attempts to gather those important details in one place for the most common KeyStores.&lt;/p&gt;

&lt;p&gt;Each key store has an overall password used to protect the entire store, and can optionally have per-entry passwords for each secret- or private-key entry (if your backend supports it).&lt;/p&gt;

&lt;h2&gt;Java Key Store (JKS)&lt;/h2&gt;

&lt;p&gt;The original Sun JKS (Java Key Store) format is a proprietary binary format file that can only store asymmetric private keys and associated X.509 certificates.&lt;/p&gt;

&lt;p&gt;Individual private key entries are protected with &lt;a href="http://www.docjar.com/docs/api/sun/security/provider/KeyProtector.html"&gt;a simple home-spun stream cipher&lt;/a&gt;—basically the password is salted (160-bits) and hashed with SHA-1 in a trivial chained construction until it has generated enough output bytes to XOR into the private key. It then stores a simple authenticator tag consisting of SHA-1(password + private key bytes) — that's the unencrypted private key bytes. In other words, this is an &lt;a href="https://en.wikipedia.org/wiki/Authenticated_encryption#Encrypt-and-MAC_.28E.26M.29"&gt;Encrypt-and-MAC&lt;/a&gt; scheme with homespun constructions both based on simple prefix-keyed SHA-1. (This scheme has OID 1.3.6.1.4.1.42.2.17.1.1).&lt;/p&gt;

&lt;p&gt;The whole archive is again integrity protected by a home-spun prefix keyed hash construction, consisting of the SHA1 hash of the UTF-16 bytes of the raw keystore password, followed by the UTF-8 bytes of the phrase "Mighty Aphrodite" (I'm not kidding) followed by the bytes of the encoded key store entries.&lt;/p&gt;

&lt;p&gt;If every part of this description has not got you screaming at your screen in equal parts terror and bemusement, then you probably haven't fully grasped how awful this is. Don't use it, even for just storing certificates — it's tampering resistance is if anything even worse than the encryption.&lt;/p&gt;

&lt;h2&gt;JCE Key Store (JCEKS)&lt;/h2&gt;

&lt;p&gt;Sun later updated the cryptographic capabilities of the JVM with the Java Cryptography Extensions (JCE). With this they also introduced a new proprietary key store format: JCEKS.&lt;/p&gt;

&lt;p&gt;JCEKS uses "PBEWithMD5AndTripleDES" to encrypt individual key entries, with a 64-bit random salt and 200,000 iterations of PBKDF1 to derive the key. TripleDES is used with 3 keys ("encrypt-decrypt-encrypt") in CBC mode. There is no separate integrity protection of individual keys, which is fine if the archive as a whole is integrity protected, but it means that access control is effectively at the level of the whole keystore. This is not &lt;em&gt;terrible&lt;/em&gt; from a crypto point of view, but can definitely be improved—neither MD5 nor &lt;a href="https://csrc.nist.gov/News/2017/Update-to-Current-Use-and-Deprecation-of-TDEA"&gt;TripleDES&lt;/a&gt; are considered secure any more, and it's been a &lt;em&gt;long&lt;/em&gt; time since anyone recommended them for new projects. However, it would also not be a trivial effort to break it.&lt;/p&gt;

&lt;p&gt;JCEKS uses the same ridiculous "Mighty Aphrodite" prefix-keyed hash as JKS for integrity protection of the entire archive. It is probably best to assume that there is no serious integrity protection of either of these key stores.&lt;/p&gt;

&lt;h2&gt;PKCS#12&lt;/h2&gt;

&lt;p&gt;Apart from these proprietary key stores, Java also supports "standard" PKCS#12 format key stores. The reason for the scare quotes around "standard" is that while it is indeed a standard format, it is a very flexible one, and so in practice there are significant differences between what "key bag" formats and encryption algorithms are supported by different software. For instance, when you store symmetric SecretKey objects in a PKCS#12 key store from Java, then OpenSSL cannot read them as they use a bag type ("secretBag" - OID 1.2.840.113549.1.12.10.1.5) that it does not understand.&lt;/p&gt;

&lt;p&gt;Java uses version 3 of the PKCS#12 standard format. It stores secret keys in the aforementioned "secretBag" format, and asymmetric private keys in "PKCS#8 Shrouded Key Bag" format (OID 1.2.840.113549.1.12.10.1.2). This just dictates the format of bytes on the disk. In both cases the actual key material is encrypted using some form of password-based encryption (PBE) mode. By default this is "PBEWithSHA1AndDESede" — "DESede" is another name for TripleDES in encrypt-decrypt-encrypt mode, so this is pretty similar to the mode used by JCEKS apart from using a slightly better (but still deprecated) hash in the form of SHA-1. By default this uses a 160-bit salt and 50,000 iterations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But&lt;/strong&gt;, there is an important improvement in the PKCS#12 implementation—&lt;em&gt;you get to choose the encryption algorithm!&lt;/em&gt; By passing in a &lt;a href="https://docs.oracle.com/javase/8/docs/api/java/security/KeyStore.PasswordProtection.html#PasswordProtection-char:A-java.lang.String-java.security.spec.AlgorithmParameterSpec-"&gt;PasswordProtection&lt;/a&gt; parameter (from Java 8 onwards) when saving a key you can specify a particular (password-based) cipher to use. I haven't checked exactly what ciphers are allowed, but you can at least specify a stronger PBE mode, such as "PBEWithHmacSHA512AndAES_256", which will derive a 256-bit AES key using salted PBKDF2 and then encrypt the stored key using AES/CBC/PKCS5Padding with that key. You can also increase the number of iterations of PBKDF2 used. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.io.FileOutputStream&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.security.KeyStore&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.security.KeyStore.PasswordProtection&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.security.KeyStore.SecretKeyEntry&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.security.SecureRandom&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.crypto.SecretKey&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.crypto.spec.PBEParameterSpec&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.crypto.spec.SecretKeySpec&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;scratch&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;KeyStore&lt;/span&gt; &lt;span class="n"&gt;keyStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;KeyStore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PKCS12"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;keyStore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;load&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Initialize a blank keystore&lt;/span&gt;

        &lt;span class="nc"&gt;SecretKey&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SecretKeySpec&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="o"&gt;],&lt;/span&gt; &lt;span class="s"&gt;"AES"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"changeit"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toCharArray&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SecureRandom&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;nextBytes&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;keyStore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setEntry&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SecretKeyEntry&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;PasswordProtection&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"PBEWithHmacSHA512AndAES_128"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;PBEParameterSpec&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100_000&lt;/span&gt;&lt;span class="o"&gt;)));&lt;/span&gt;

        &lt;span class="n"&gt;keyStore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;store&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FileOutputStream&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/tmp/keystore.p12"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that despite the inclusion of "HmacSHA512" in the above PBE mode that only applies to the key derivation from the password. There is no integrity protection at the level of individual entries.&lt;/p&gt;

&lt;p&gt;It is also worth noting that the keystore and individual key passwords &lt;em&gt;should be the same&lt;/em&gt;. I don't think this is a fundamental limitation of PKCS#12 in Java, but certainly standard Java tools like the command line "keytool" utility will fail to handle PKCS#12 keystores with different passwords used for the store vs individual keys. If you don't need to use those tools then you might be able to get away with different passwords for each key.&lt;/p&gt;

&lt;p&gt;In contrast to the previous entries, the PKCS#12 key store format does actually encrypt certificates too. It does this with a hard-coded algorithm "PBEWithSHA1AndRC2_40". This uses 50,000 rounds of salted PBKDF1 to derive a &lt;em&gt;40-bit&lt;/em&gt; key for RC2 encryption. RC2 is an old stream cipher that I certainly wouldn't recommend. The 40-bit key is &lt;em&gt;far&lt;/em&gt; too small to provide any serious security. It makes me wonder why bother applying 50,000 rounds of PBKDF1 to protect the password while generating a key that is itself vulnerable to brute-force. It is probably actually faster to brute force the derived key than the original password. I can only assume it is maintaining compatibility with some decision taken way back in the depths of time that everyone involved now deeply regrets.&lt;/p&gt;

&lt;p&gt;The integrity of the overall PKCS#12 key store is protected with "HmacPBESHA1". This is HMAC-SHA1 using a key derived from the store password using 100,000 iterations of salted PBKDF2-HMAC-SHA1. This is all hard-coded so cannot be changed. This is an ok choice, although it would be nice to be able to use something other than SHA-1 here, as it appears that PKCS#12 allows other MACs to be used. For HMAC usage, SHA-1 is still just about ok for now, but it would be better to remove it. It would also be nice to be able to tune the iteration count.&lt;/p&gt;

&lt;p&gt;Overall, the PKCS#12 key store is considerably better than either of the Sun-designed proprietary options. If you specify your own PasswordProtection instances with AES and SHA2 and use high iteration counts and good random salts, then it's actually a pretty solid design even by modern standards. The only really ugly part is the 40-bit RC2 encryption of trusted certificates, but if you do not care about the confidentiality of certificates then we can overlook that detail and just consider them lightly obfuscated. At least the use of HMAC-SHA1 is a decent integrity protection at last.&lt;/p&gt;

&lt;h2&gt;PKCS#11&lt;/h2&gt;

&lt;p&gt;There's not much to say about PKCS#11. It is a standard interface, intended for use with &lt;em&gt;hardware&lt;/em&gt; security tokens of various kinds: in particular Hardware Security Modules (HSMs). These range from &lt;a href="https://shop.nitrokey.com/shop/product/nitrokey-hsm-7"&gt;50 Euro USB sticks&lt;/a&gt; up to network-attached behemoths that cost tens or hundreds of thousands of dollars. The hardware is usually proprietary and closed, so it's hard to say exactly how your keys will be stored. Generally, though, there are significant protections against access to keys from either remote attackers or even those with physical access to the hardware and a lot of time on their hands. This isn't a guarantee of security, as there are lots of ways that keys might accidentally leak from the hardware, as the recent &lt;a href="https://crocs.fi.muni.cz/public/papers/rsa_ccs17"&gt;ROCA vulnerability in Infineon hardware&lt;/a&gt; demonstrated. Still, a well-tested HSM is probably a pretty secure option for high-value keys.&lt;/p&gt;

&lt;p&gt;I won't go into the details of how to set up a PKCS#11 key store, as it really varies from vendor to vendor. As for PKCS#12, while the interface is standardised there is enormous room for variation within that standard. In most cases you would let the HSM generate keys in the secure hardware and never export the private key material (except perhaps for backup).&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;Use a HSM or a PKCS#12 keystore, and specify manual PasswordProtection arguments when storing keys.  Avoid the proprietary key stores. &lt;/p&gt;

&lt;p&gt;Alternatively, farm out key management to somebody else and use a Key Management System (KMS) like &lt;a href="//www.vaultproject.io"&gt;Hashicorp Vault.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>cryptography</category>
      <category>keystore</category>
    </item>
    <item>
      <title>7 Best Practices for JSON Web Tokens</title>
      <dc:creator>Neil Madden</dc:creator>
      <pubDate>Wed, 25 Jan 2017 13:56:34 +0000</pubDate>
      <link>https://forem.com/neilmadden/7-best-practices-for-json-web-tokens</link>
      <guid>https://forem.com/neilmadden/7-best-practices-for-json-web-tokens</guid>
      <description>&lt;p&gt;&lt;strong&gt;Update 15th March 2017&lt;/strong&gt;: &lt;em&gt;Given recent criticism of the JWT and JOSE specifications, I've written some notes on &lt;a href="https://neilmadden.wordpress.com/2017/03/15/should-you-use-jwt-jose/"&gt;should you use JWT/JOSE?&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/JSON_Web_Token"&gt;JSON Web Tokens&lt;/a&gt; (JWTs, pronounced "jots") are gaining in popularity as a way to securely transmit small packets of information, such as session tokens, proof of identity, and network protocol messages. While there are a great many libraries available that make constructing and verifying JWTs straightforward, it is also easy to misuse them and end up compromising the very security properties you wanted to achieve. In this article, &lt;a href="https://neilmadden.wordpress.com/"&gt;I&lt;/a&gt; outline some best practices to ensure that your information stays secure.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Take time to learn about the underlying security properties
&lt;/h2&gt;

&lt;p&gt;It is easy to think of cryptography libraries as a black box. You pick a library, read the docs, and before long you have sprinkled a little digital signature or encryption magic dust on your application and moved on to the next task. This is a mistake. Even with the most carefully designed and implemented library, a lack of knowledge of the security properties that it provides and how it provides them can lead to fatal flaws when used incorrectly.&lt;/p&gt;

&lt;p&gt;JWT libraries provide a lot of confusing options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Symmetric Message Authentication Codes (MACs) based on &lt;a href="https://en.wikipedia.org/wiki/Hash-based_message_authentication_code"&gt;HMAC&lt;/a&gt; with &lt;a href="https://en.wikipedia.org/wiki/SHA-2"&gt;SHA-256, SHA-384 or SHA-512&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Digital signatures based on &lt;a href="https://en.wikipedia.org/wiki/RSA_(cryptosystem)"&gt;RSA&lt;/a&gt; or &lt;a href="https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm"&gt;Elliptic Curve DSA&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Symmetric authenticated encryption based on &lt;a href="https://en.wikipedia.org/wiki/Advanced_Encryption_Standard"&gt;AES&lt;/a&gt; in &lt;a href="https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#CBC"&gt;CBC mode&lt;/a&gt; or AES in &lt;a href="https://en.wikipedia.org/wiki/Galois/Counter_Mode"&gt;GCM&lt;/a&gt; mode.&lt;/li&gt;
&lt;li&gt;Public key encryption using RSA with various padding modes (&lt;a href="https://tools.ietf.org/html/rfc2313"&gt;PKCS#1.5&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Optimal_asymmetric_encryption_padding"&gt;OAEP&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Key agreement protocols such as &lt;a href="https://en.wikipedia.org/wiki/Elliptic_curve_Diffie%E2%80%93Hellman"&gt;ECDH&lt;/a&gt; or &lt;a href="https://tools.ietf.org/html/rfc2898#section-6.2"&gt;password-based&lt;/a&gt;, and various key-wrapping modes.&lt;/li&gt;
&lt;li&gt;Compression of the payload.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These options can be bewildering at first, and you need to pick carefully to get the security properties you desire. For instance, to protect session tokens issued and consumed by the same application, it may be reasonable to use a symmetric encryption mode such as AES-GCM. This provides both confidentiality of the content of the session token and integrity and authenticity to prevent forgeries. However, a public key encryption scheme such as RSA would be wholly inappropriate in this case, as anybody with the &lt;em&gt;public&lt;/em&gt; key can then create a valid session token.&lt;/p&gt;

&lt;p&gt;Taking some time to learn about the security properties and how the underlying cryptographic primitives provide them will pay dividends in the long run. The &lt;a href="https://www.coursera.org/learn/crypto"&gt;Coursera Crypto I course&lt;/a&gt; will give you a good start.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Don't go overboard
&lt;/h2&gt;

&lt;p&gt;With the plethora of modes described in the previous point, it can be tempting to go overboard and use a bit of everything. This is often unnecessary. For instance, if you want to ensure confidentiality and authenticity of your own JWTs then it is is sufficient to use one of the symmetric encryption modes, as &lt;a href="https://en.wikipedia.org/wiki/Authenticated_encryption"&gt;these are already authenticated.&lt;/a&gt; You can either directly encrypt the JWTs with a shared key, or use one of the key-wrapping modes. It is certainly not necessary to also then apply a separate HMAC, unless you are very paranoid about security margins. (The better idea is to rotate your keys frequently, see below). The more options you use, the more complex your system becomes to reason about and the more credentials you potentially have to manage.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Plan for how you will manage your keys
&lt;/h2&gt;

&lt;p&gt;The weakest part of any system's security is often the key management. If a key is compromised then the security properties are no longer guaranteed: messages may be decrypted, security tokens forged, and other parts of your system breached as a result. You should follow best practices for managing your keys:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use secure storage for all keys that is not easily accessed in case of a breach. Consider using a &lt;a href="https://en.wikipedia.org/wiki/Hardware_security_module"&gt;Hardware Security Module (HSM)&lt;/a&gt; or a dedicated key management service running on a separate host such as &lt;a href="https://www.vaultproject.io/"&gt;Vault&lt;/a&gt; or &lt;a href="https://aws.amazon.com/kms/"&gt;Amazon KMS&lt;/a&gt;. Make sure appropriate access and audit controls are in place.&lt;/li&gt;
&lt;li&gt;Rotate keys often, such as once a day or week or month, depending on usage volumes.&lt;/li&gt;
&lt;li&gt;Use a high-quality source of random data for generating keys. Usually this means /dev/random or /dev/urandom on UNIX-like systems, or a dedicated hardware random data generator. If you must use passwords, then use a high-quality password-based key derivation algorithm such as &lt;a href="https://en.wikipedia.org/wiki/Bcrypt"&gt;bcrypt&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Scrypt"&gt;scrypt&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Argon2"&gt;Argon2&lt;/a&gt; or &lt;a href="https://en.wikipedia.org/wiki/PBKDF2"&gt;PBKDF2&lt;/a&gt;. Use high iteration counts (e.g. &lt;a href="https://pages.nist.gov/800-63-3/sp800-63b.html#memorized-secret-verifiers"&gt;NIST recommends at least 10,000 iterations for PBKDF2&lt;/a&gt;) and unique per-key salts when applicable.&lt;/li&gt;
&lt;li&gt;Immediately rotate any keys suspected of compromise and stop trusting any JWTs using that key.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Consider using "headless" JWTs
&lt;/h2&gt;

&lt;p&gt;A JWT consists of a protected payload together with a plaintext "header" section. This can contain various bits of information such as the algorithms used to sign or encrypt the payload or application-specific information to be used by intermediaries on the network, e.g. for message routing. In a lot of cases, this information is redundant and &lt;a href="https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/"&gt;it is downright dangerous to trust its contents anyway&lt;/a&gt;. If you do not need to interoperate with third parties that expect standard JWTs, you can save some space and eliminate a whole class of vulnerabilities by simply stripping off the header section when producing a JWT and then recreate it from known data before parsing. I call these "headless JWTs" and recommend you use them wherever you can.&lt;/p&gt;

&lt;p&gt;Stripping the header is easy: just remove everything up to the first "." character in the encoded JWT. To reconstruct the JWT, just base64url-encode a fixed header identifying the known algorithm and parameters and prepend it to the headless JWT.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Be careful when using encryption and compression together
&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://breachattack.com"&gt;Combining encryption with compression can cause information leaks if you are not careful&lt;/a&gt;. This is not just a theoretical vulnerability as practical attacks have been shown. If an attacker is able to control any information in the same encrypted block as some sensitive information, then compression may leak information about the secret parts. Compressing a JWT can be a big win when space is at a premium (e.g. for HTTP cookies), but it should be weighted up against the potential risks. If you need confidentiality and really want compression too, some options to consider include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://crypto.stackexchange.com/a/37936/26028"&gt;Padding the compressed content to some fixed size&lt;/a&gt; that you are happy with. You may still get a decent compression ratio with this.&lt;/li&gt;
&lt;li&gt;Segregate your data into secret information controlled by your application, and non-secret information controlled by user input. Place the secret information into the encrypted &amp;amp; compressed payload and the user-supplied information into the uncompressed (and unencrypted) JWT header. This way the user-controlled information cannot alterÂ the compression of the secret information. If the user-supplied information should also be encrypted, then consider using two separate JWTs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. Consider JWT lifetimes and revocation
&lt;/h2&gt;

&lt;p&gt;Where JWTs are used to convey authority, best practice is to limit the period of time that the JWT is valid for. If JWTs must be long-lived, then investigate options for revoking JWTs to prevent further use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://neilmadden.wordpress.com/2016/02/25/stateless-session-logout-in-openam-13/"&gt;Blacklisting JWTs&lt;/a&gt; based on a unique ID can be made scalable and efficient, but defaults to JWTs being trusted in the absence of information.&lt;/li&gt;
&lt;li&gt;Have short-lived JWTs and require them to be re-issued regularly (e.g. via an &lt;a href="https://tools.ietf.org/html/rfc6749#section-1.5"&gt;OAuth2 refresh token flow&lt;/a&gt;). This can be a suitable compromise when the clients are programmatic and so can automatically refresh tokens periodically.&lt;/li&gt;
&lt;li&gt;Use JWTs only to identify resources and some minimal state, while storing the majority of data on the server. The database stores state as normal with a unique identifier (e.g. UUID). The JWT is constructed by the application layer from this unique ID and some minimal metadata. This may seem like the worst of all worlds, but is actually quite a sensible default for a number of reasons:
     1. State is kept on the server and can easily be managed, audited and revoked (deleted).
     2. Protections in the JWT (e.g. HMAC) allow for a quick check of validity before hitting a central database resource.
     3. If tokens are stored in the database but signed/verified by the application layer on-the-fly using a key stored separately, then an attacker must compromise both systems in order to forge or steal tokens.
     4. State can be moved from the JWT toÂ the database and vice versa over time as requirements change.
     5. Larger amounts of state can be stored in the database than can typically be toleratedÂ in a JWT, and it is much easier to update it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  7. Read the Security Considerations!
&lt;/h2&gt;

&lt;p&gt;Like most RFCs, the JWT specs contain &lt;a href="https://tools.ietf.org/html/rfc7518#section-8"&gt;Security Considerations&lt;/a&gt; sections that detail common threats and advice on how to avoid them. You should read all of these and make sure you understand them before deploying a JWT-based solution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://tools.ietf.org/html/rfc7515#section-10"&gt;RFC 7515: JSON Web Signatures&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tools.ietf.org/html/rfc7516#section-11"&gt;RFC 7516: JSON Web Encryption&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tools.ietf.org/html/rfc7517#section-9"&gt;RFC 7517: JSON Web Key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tools.ietf.org/html/rfc7518#section-8"&gt;RFC 7518: JSON Web Algorithms&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You should also read &lt;a href="http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/"&gt;common criticisms of JWT&lt;/a&gt;-based solutions. While I believe that article overplays the risks (there are reasonable mitigations available), it makes some valid points that you should consider before betting the farm on JWTs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;I hope this article has given you some solid advice on building robust and secure JWT-based solutions. When used carefully and with plenty of planning, JWTs can form the basis of highly scalable and reliable systems. By following the best practice in this article, you should be able to put appropriate protections in place to ensure that your data stays secure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you liked this article, you'll love my book&lt;/strong&gt;: &lt;a href="https://www.manning.com/books/api-security-in-action"&gt;API Security in Action&lt;/a&gt;&lt;/p&gt;

</description>
      <category>jwt</category>
      <category>json</category>
      <category>security</category>
    </item>
    <item>
      <title>Hi, I'm Neil Madden</title>
      <dc:creator>Neil Madden</dc:creator>
      <pubDate>Sun, 15 Jan 2017 23:09:53 +0000</pubDate>
      <link>https://forem.com/neilmadden/hi-im-neil-madden</link>
      <guid>https://forem.com/neilmadden/hi-im-neil-madden</guid>
      <description>&lt;p&gt;I have been coding for ~25 years (18 years professionally).&lt;/p&gt;

&lt;p&gt;You can find me on GitHub as &lt;a href="https://github.com/NeilMadden" rel="noopener noreferrer"&gt;NeilMadden&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I live in the UK. &lt;/p&gt;

&lt;p&gt;I am a freelance software engineer and application security consultant. &lt;/p&gt;

&lt;p&gt;I mostly program in these languages: Java, C, Tcl, Prolog, Scheme and a little ML or Haskell every now and then. &lt;/p&gt;

&lt;p&gt;I am currently learning more about Erlang/Elixir and Go.&lt;/p&gt;

&lt;p&gt;Nice to meet you.&lt;/p&gt;

</description>
      <category>introduction</category>
    </item>
  </channel>
</rss>
