[HN Gopher] Advice for Operating a Public-Facing API
       ___________________________________________________________________
        
       Advice for Operating a Public-Facing API
        
       Author : CharlesW
       Score  : 61 points
       Date   : 2023-07-22 00:36 UTC (1 days ago)
        
 (HTM) web link (jcs.org)
 (TXT) w3m dump (jcs.org)
        
       | pledess wrote:
       | Adding more structure to prefixed tokens could help avoid false
       | positives when someone signs up for GitHub secret scanning. I
       | notice that Pushover is apparently not signed up:
       | https://docs.github.com/en/code-security/secret-scanning/sec...
        
       | mattbee wrote:
       | Did this page just turn into flying toasters when I wasn't
       | looking?
        
         | esafak wrote:
         | Yes. https://jcs.org/js/afterdark-min.js
         | 
         | https://en.wikipedia.org/wiki/After_Dark_(software)
        
       | wizofaus wrote:
       | That last suggestion (of returning 200 but with a message
       | explaining that usage limit has been reached) seems odd to me -
       | I'm not saying I haven't seen code that simply retries on any
       | error but that could just as well include an error trying to
       | parse the response and extract meaningful values from it. What I
       | have observed is that client code often logs or relays HTTP
       | status response codes (and 429 explicitly exists for this case)
       | but rarely bothers doing the same for unexpected message content,
       | which at best might be logged or conveyed to an end user as some
       | sort of "failed to parse" exception. Surely a better option to
       | avoid getting hammered is to return 429 after a 15-20 second
       | delay?
        
         | whartung wrote:
         | I think the premise here is that a 4xx is an "expected" server
         | issue, which the code may be able to handle (i.e. retry)
         | whereas a 200 followed by a parse error is an "application
         | problem" that they're not prepared to handle.
         | 
         | A 200 may mean the payload has changed, and how would an app
         | handle an arbitrary format change? This could well fall into
         | the "don't test for something you can't handle".
         | 
         | At a minimum it'll ideally get the app to quiet down.
        
           | capableweb wrote:
           | > I think the premise here is that a 4xx is an "expected"
           | server issue
           | 
           | That premise is incorrect, as 4xx is client errors, as in the
           | client formatted the request wrong or anything else, and
           | therefore it couldn't be responded to. Rate-limiting is the
           | client hitting the server too much, and it's up the client to
           | handle this.
           | 
           | 5xx is for server issues.
           | 
           | 2xx should be success in any shape or form, so clearly 2xx
           | shouldn't be used in this case either.
           | 
           | I agree that 429 should just be used for it's intended
           | purpose here, handling rate-limiting requests/responses. You
           | can still add a body if you want, with the current quotas.
        
       | smallnix wrote:
       | The token prefix is a nice hack, but users will find it out and
       | then it becomes part of the informal API.
        
         | 8organicbits wrote:
         | I don't think the AKIA/ASIA prefix for AWS access keys is
         | formalized, which may be a good example of this:
         | https://github.com/localstack/localstack/blob/6f846a8278e439...
        
         | [deleted]
        
       | brendoncarroll wrote:
       | It's amazing how far adrift the industry has gone with
       | authentication.
       | 
       | This post is saying to avoid OAuth and use bearer tokens because
       | OAuth is too complicated. I agree with OAuth being too
       | complicated, but I don't really think bearer tokens are the
       | solution either.
       | 
       | Now there are jwts, and passkeys, and all these other solutions,
       | which from where I'm standing, just look like someone else's
       | resume-builder that I'm going to have to understand in a few
       | years in order to do something simple and unrelated.
       | 
       | We are already connecting over TLS, just have the client
       | authenticate with a long lived asymmetric key. Let me see that
       | key in whatever web framework; I should have access to it, same
       | as an HTTP header. Then I'll stick it in the database, maybe hash
       | it first, if it's big. It doesn't have to be harder than that,
       | your identity is (the hash of) your public key.
        
         | AlphaSite wrote:
         | JWTS (and related token type approaches) are a solution to the
         | whole: how do I avoid spending time doing authn on every
         | request?
        
         | dilyevsky wrote:
         | If you use mTLS client identity is proven cryptographically
         | (normally via /CN x509 field) - no need to exchange the key
         | during authentication. You still need to generate it and
         | distribute it to the user and manage its lifecycle which gets
         | you to the same place as OAuth except with worse library
         | support
        
           | brendoncarroll wrote:
           | > no need to exchange the key during authentication
           | 
           | The public key does need to be exchanged, along with a
           | signature relating it to the current session. This is all
           | handled by TLS, there is no need for the client to send the
           | key in the application data.
           | 
           | > You still need to generate it and distribute it to the user
           | 
           | This approach avoids distributing secret key material at all.
           | Private keys should ideally never move. They are generated
           | randomly, used to derive the corresponding public key, and
           | then persisted as appropriate. The public key is sent around
           | to other parties.
        
             | dilyevsky wrote:
             | How do you ensure someone else didn't just create a new
             | cert with the same user id? At the minimum there needs to
             | be a step to sign the public key (with another flow to
             | prove csr requester identity) Do you see how this a lot
             | more moving pieces than oauth the user needs to figure out?
             | 
             | If you're suggesting to just store a cert thumbprint that
             | means a db call on every request - no different than just a
             | secret token.
        
         | willseth wrote:
         | Users want to be able to use their existing identity providers.
         | At a minimum it's a red flag for consumers if you don't give
         | them the option to sign in with Google, etc. - and it's simply
         | a deal breaker for many enterprise customers if you can't
         | integrate with their IDP.
         | 
         | I wish implementing auth wasn't so complicated now, but the
         | idea that we can just decide to make it so by doing it another
         | way is a fantasy. That ship has sailed.
        
       | butz wrote:
       | What about CORS and CSP headers? Should public/open APIs use them
       | and prevent building client side only apps?
        
         | gwbas1c wrote:
         | Why would you want to block that?
        
       ___________________________________________________________________
       (page generated 2023-07-23 23:01 UTC)