[HN Gopher] OAuth with Cloudflare workers on a statically genera...
       ___________________________________________________________________
        
       OAuth with Cloudflare workers on a statically generated site
        
       Author : vonadz
       Score  : 167 points
       Date   : 2021-11-15 10:54 UTC (12 hours ago)
        
 (HTM) web link (abyteofcoding.com)
 (TXT) w3m dump (abyteofcoding.com)
        
       | Lucasoato wrote:
       | I absolute love the graph, really. When the idea is simple and
       | easy, you don't need hundreds of tools, just the plain old paint
       | is fine.
        
         | vonadz wrote:
         | Thanks :) paint is the graphic editor I'm most proficient in!
        
       | jimhi wrote:
       | Fantastic use of workers!
       | 
       | I added the ability to do captcha submissions from my site and
       | send alerts to slack myself. I opted not to go the worker route
       | as I found the language a bit hard to use and I could get the
       | same effect with just javascript pulling other dynamic javascript
       | hosted elsewhere.
       | 
       | (You can see an example with the submission form at the bottom of
       | this page: https://mrsteinberg.com/how-to-kill-your-startup-co-
       | founder-...)
        
         | ignoramous wrote:
         | > _Fantastic use of workers!_
         | 
         | Well, when you think of Workers as Nginx, Squid, Memcached as-
         | a-service, the possibilities simply present themselves. It is
         | absolutely appalling that AWS has Lambda@Edge (relatively, uber
         | expensive) and CloudFront Functions (uber lame) positioned
         | against Workers.
         | 
         | Full-stack week starting today, and it is very likely that
         | Cloudflare launch _Container_ support for Workers:
         | https://blog.cloudflare.com/full-stack-week-2021/
         | 
         | Let's see if Adam Selipsky announces anything compelling at
         | re:invent aloof from their Lightsail initiatives which are
         | priced similar to Cloudflare (and cheap only if you're running
         | toy products atop, but not any SaaS-like services).
        
         | tyingq wrote:
         | > I opted not to go the worker route as I found the language a
         | bit hard to use and I could get the same effect with just
         | javascript pulling other dynamic javascript hosted elsewhere
         | 
         | I'm confused by this since the default language for Workers is
         | javascript. Do you mean their api is confusing?
        
           | adamkochanowicz wrote:
           | Same question.
        
           | jimhi wrote:
           | I answered above - looking at their site it appears there is
           | much more documentation. It was hard to wrap my head around
           | what it was doing / the APIs when I wrote this
        
         | vonadz wrote:
         | Thanks! I'd like to explore adding debugging and warning alerts
         | in the future. Right now it's kind of hard to tell if anything
         | is broken, short of going through the registration process
         | myself. If you're pulling javascript hosted somewhere else to
         | your site, doesn't that expose your slack API key?
        
           | jimhi wrote:
           | I should have explained more. The javascript is dynamically
           | created and hosted on S3. The keys, etc are safely on a
           | server that runs to generate the file. I built this around
           | the time Cloudflare first released workers, their
           | documentation seems much less confusing now.
        
             | vonadz wrote:
             | I'm having a hard time understanding how a file hosted on
             | S3 can send a request to Slack without exposing your API
             | key. Can you elaborate on that?
             | 
             | EDIT: guessing by the delay in response, someone just told
             | all of HN they exposed their API key?
        
               | DangitBobby wrote:
               | My understanding is that they used cloud functions. Code
               | is being executed on someone else's server, not the
               | client, so the keys don't have to be shared with the
               | client.
        
               | vonadz wrote:
               | That would be the logical solution, but "The javascript
               | is dynamically created and hosted on S3. The keys, etc
               | are safely on a server that runs to generate the file"
               | sounds a lot like they have a server where they build a
               | .js file that is capable of querying Slack, then store
               | that file on S3 for the website to pull whenever someone
               | registers. In that case, the client is pulling a .js file
               | that probably has the Slack API key in it.
        
         | [deleted]
        
       | fzaninotto wrote:
       | I don't understand how you can log out using this method, and
       | that's very concerning. You're basically logged in forever?
        
         | vonadz wrote:
         | There is no logout because the login isn't really a login. All
         | this is doing is using the user's permission to submit their
         | email (registered on the OAuth service) to subscribe to the
         | newsletter. Nothing in the browser is changing that could
         | compromise your details.
        
       | intricatedetail wrote:
       | Can you self host these workers? Otherwise you get vendor lock in
       | which is a no go.
        
         | ignoramous wrote:
         | Yes, miniflare [0] lets you run Workers locally, but I wouldn't
         | treat it to production traffic.
         | 
         | There's also Deno, which is _very_ similar in technology to
         | Workers [1].
         | 
         | Others are building "Workers" atop WebAssembly, and things are
         | looking up on that front as well [2][3].
         | 
         | See also: https://github.com/debarshibasak/awesome-paas
         | 
         | [0] https://github.com/cloudflare/miniflare
         | 
         | [1] https://deno.land
         | 
         | [2] https://github.com/suborbital/atmo
         | 
         | [3] https://github.com/krustlet/krustlet
        
         | vonadz wrote:
         | Self hosting would pretty much defeat the whole purpose of
         | workers. The point is that you don't need to self host.
        
           | nicoburns wrote:
           | The point is that you don't need to host them in production.
           | Being able to self-host is still very useful for testing and
           | local development workflows
        
           | lsaferite wrote:
           | Their point is, can you mitigate vendor lock-in if you need
           | to do so? The fact that you don't even consider that is a sad
           | commentary in itself.
        
             | ezfe wrote:
             | It's regular Javascript, so if you program it properly then
             | you can re-use a lot of code with minimal work. Depends on
             | how you architect your project to say how easy it would be.
        
             | vonadz wrote:
             | If their point was can you mitigate vendor lock-in, they
             | should have said that instead of asking about self-hosting.
             | Saying you have vendor lock-in because you can't self-host
             | something is very strange in the context of this article.
             | 
             | I didn't make a point of vendor lock-in because migrating
             | this process flow to a self-hosted HTTP server would take
             | about 5 minutes. On top of that, this flow is going to be
             | very similar for any vendor offering javascript functions.
             | 
             | Perhaps it is my fault for not including a section
             | discussing this, but I assumed that the audience for this
             | would primarily be people understand basic javascript and
             | could deduce the portability of the code by looking at it.
        
       | jbergstroem wrote:
       | At my company we've been using workers extensively for routing,
       | specific auth logic (including integration with Auth0) and more
       | -- I guess moving towards an api gateway pattern. I loved it at
       | first but its becoming very cumbersome to maintain. I'm currently
       | migrating away from this pattern and try to keep logic closer to
       | the application/code that leans on it.
       | 
       | tl;dr: Orchestrating many cloudflare workers at scale has not
       | been a great experience.
        
         | vonadz wrote:
         | Yeah I don't find this at all surprising. Ultimately it's
         | always a balance of what's worse to maintain, the reality
         | (server) or the abstraction (workers).
        
       | techthumb wrote:
       | From the article itself:                 ... one might think
       | implementing OAuth sign up is relatively trivial; after all, you
       | just need to write a fetch request that redirects the user to the
       | OAuth page, then another request that sends their email to the
       | newsletter service of choice to sign them up. Well, the issue is
       | that in order to do the second step of that process, one needs to
       | hit an API endpoint that requires authentication (an API key).
       | That is essentially a password and not something you want to
       | expose on the front end and give everyone access to.
       | 
       | The OAuth Authorization Code Flow with Proof Key for Code
       | Exchange (PKCE) solves this problem without needing a worker.
       | 
       | This article Auth0 does a good job of explaining PKCE:
       | https://auth0.com/docs/authorization/flows/authorization-cod...
        
         | vonadz wrote:
         | I think you misunderstood what I said. The API key I don't want
         | to expose is the one that is required to register the user with
         | the newsletter service, not the client key for the OAuth
         | service.
        
           | DaiPlusPlus wrote:
           | OAuth doesn't use "API keys". Please clarify.
        
             | vonadz wrote:
             | "not the client key for the OAuth service"
             | 
             | OAuth uses a client key and/or a client secret, for the
             | application that is requesting access on behalf of the
             | client.
        
               | DaiPlusPlus wrote:
               | OAuth + OIDC only uses client-secrets when using the
               | client_credentials flow, which is only for us with non-
               | human software, or when a client needs to authenticate
               | and authorize itself independently of any human user.
               | When humans are involved you won't be using
               | client_credentials, you'll be using 'implicit' or 'code'
               | (preferably with PKCE) - but ONLY when the client can
               | actually safely store secrets - so static-website SPAs
               | simply can't.
               | 
               | While non-human client-credentials can be used in-
               | conjunction with a human-user's credentials it's largely
               | unnecessary as an unauthorized client wouldn't be able to
               | authenticate with a human-user because the redirect_uri
               | sent from the client would be rejected automatically (and
               | if that worked, there's always 'aud' audience filtering
               | too), so the human-user wouldn't even be prompted to
               | authenticate, they'd get an error message.
        
         | DaiPlusPlus wrote:
         | The problem isn't about secure transmission of the
         | access_token, it's about secure storage of the access_token:
         | it's impossible to safely and securely store secrets in
         | browser-based (JS) OIDC clients when using OIDC's Implicit
         | flow, which is the only flow that works with client-side-JS
         | applications (especially SPAs).
         | 
         | Conventional web-applications let the application server store
         | per-user secrets (e.g. access_tokens). If the application
         | server needs to be stateless then secrets are packed into a
         | web-browser cookie with the "httponly" and "secure" attributes
         | which prevents any and all client-scripts from accessing them.
         | Of course browser cookies are not the same thing as a true
         | Bearer Token, so this means that when using an SPA the SPA
         | cannot make its own HTTP requests to other RPs, it needs to use
         | some non-local secret-storing-proxy to make the request for
         | it... which starts to make a mockery of how microservices
         | should operate.
         | 
         | Code Flow with PKCE does not replace the Implicit flow. Also,
         | the Auth0 article you linked to is not a "good job". On the
         | contrary, that article talks about using client-secrets - which
         | you *must never have* in a JS-only/SPA/static client.
         | 
         | The only real solution would be some kind of opaque OIDC client
         | built-in to a browser that handles secrets-storage on-behalf of
         | JS applications (such that JS code never gets to see or handle
         | any secrets, including the auth code and access_token, but the
         | OIDC identity_token should be exposed, of course). I'm
         | surprised Google and Mozilla haven't done this already...
        
       | noahmasur wrote:
       | Why not just use Cloudflare Access for this? It's the same thing
       | for even less work (and it's free for personal use).
        
         | vonadz wrote:
         | Did you read the article?
        
         | judge2020 wrote:
         | This worker might be cheaper depending on how heavy your app is
         | (eg. how many requests this worker triggers on) versus Access
         | if you have >50 users.
        
         | vonadz wrote:
         | Not quite sure why my other comment got flagged, it was a
         | genuine question. If they had, and they still suggested this, I
         | would inquire how that would be possible. It appeared to me
         | that they had just read the title of the article and suggested
         | something related to it.
         | 
         | As far as I can tell, Cloudflare Access doesn't allow you to
         | run arbitrary code in an environment that isn't exposed to the
         | user, which is kind of the whole purpose of this setup. The
         | sole purpose of the OAuth part of this operation is so that the
         | user doesn't have to type in their email. Session
         | persistence/selective access isn't relevant here, and that
         | appears to be the only thing the Cloudflare Access really
         | offers.
        
       | nawgz wrote:
       | "Instead of using a single server with NGINX and an API on it, I
       | use multiple external hosted services that cost more-per-request
       | than an old-school setup with less portability and more vendor
       | lock-in"
       | 
       | This isn't even a technical accomplishment in any way, it's just
       | slapping together a few managed services together to sign up
       | someone for a newsletter. I cannot imagine being the one to
       | maintain a signup flow like this, it certainly looks
       | unnecessarily painful from here.
        
         | vonadz wrote:
         | In regards to your quote, this is free and if I wanted to
         | switch, I could just copy and paste the javascript into node
         | with some minor tweaks.
         | 
         | A big motivator for this was definitely just to try out
         | Cloudflare workers and see how they are. I've set up countless
         | servers for APIs. In terms of time, I'd say Cloudflare workers
         | is a bit faster when you get over the initial learning curve.
         | Obviously you could write a deploy script for a server and have
         | it set up everything automatically, and I have done that in the
         | past, but sometimes it's fun to try new things right?
         | 
         | I never intended for this to come across as a technological
         | accomplishment. I even end the article with "That's pretty much
         | it. It's fairly simple with no real catches". I'm merely
         | presenting what I thought would be useful information for some
         | people. Personally I think maintaining a server is more work
         | than maintaining this, but to each their own.
        
           | jffry wrote:
           | Thanks for sharing a small writeup of a neat thing you did! I
           | think maybe the parent comment missed the context, which is
           | that you wanted to add an email signup to an otherwise static
           | site.
           | 
           | In that context, setting up a VPS would now mean that you
           | have to be responsible for a new pet, including security
           | updates and monitoring. You would also have to change your
           | deployment tooling / workflow to something quite different
           | (pushing and restarting a running service, rather than just
           | running aws s3 sync ...)
           | 
           | Of course I don't think I would take this approach if I
           | already had a backend service hosting a site, but I certainly
           | would experiment with it if I were in your situation.
        
       | toastal wrote:
       | To quote Sourcehut Pages Limitations
       | (https://srht.site/limitations)
       | 
       | > Connections from CloudFlare's reverse proxy are dropped. Do not
       | help one private company expand its control over all internet
       | traffic.
       | 
       | We really to not let the internet become so centralized.
        
         | SergeAx wrote:
         | They are working via WARP VPN, which is good. I wonder how do
         | they differ those services, by headers only?
        
         | GrayShade wrote:
         | Good, it's not up to Sourcehut to decide how I should expose a
         | web service (or browse the Internet FWIW).
        
           | roberto wrote:
           | They're not? You're free to not use Sourcehut.
        
         | miyuru wrote:
         | Cloudflare is the only provider that I know of that provides
         | IPv6 reverse proxy for free with fair limits.
         | 
         | If it wasn't for them most of my sites won't be accessible for
         | more than half of the internet.
        
           | guilhas wrote:
           | For "free"
           | 
           | Also maybe there is a reasons for most of the internet not to
           | care about ipv6 or current implementation, but that is
           | another different big debate
        
             | ohyeshedid wrote:
             | What would those reasons be?
        
         | Eikon wrote:
         | Even if I don't agree with his opinion, I really don't
         | understand why so much people actually use cloudflare.
         | 
         | SSL is a solved problem since let's encrypt, cloudflare
         | actually decreases performance (by adding an hop when serving
         | dynamic content). For most websites, DDoS attacks are a non-
         | issue.
         | 
         | It just feels like, unnecessary technology?
        
           | handrous wrote:
           | Their service is great if you take money online at all. The
           | $200/m tier plan, that is. I gather the $5,000+/m custom
           | plans are nice if you need all the extra networking features,
           | though way overpriced if you just need basic CDN features--
           | which includes some kind of firewall, DDOS protection,
           | e-commerce attack protection (e.g. anti-credit-card-stuffing)
           | and light routing/rewriting/"worker" features at this point,
           | all of which are quickly becoming table stakes in that
           | market.
           | 
           | The free tier is great for serving low-value (that is, not
           | enough value that you _need_ a SLA from your vendor) static
           | sites for pennies a month.
           | 
           | Having so much in one place is _really_ nice for small shops.
           | 
           | But they 100% are on track to be the next Big Bad of the tech
           | world, and they're heading that way very much on purpose.
           | Their entire strategy for how they've positioned themselves
           | is, transparently, bent toward making themselves the Web's #1
           | middle-man.
        
           | GrayShade wrote:
           | I've recently started using their DNS service and I've been
           | using 1.1.1.1 for a couple of years now. I think Cloudflare
           | has done more for the Internet than a lot of other large
           | companies, and I'm inclined to trust them regardless of what
           | the sr.ht founder says.
           | 
           | Their CAPTCHAs are annoying, though, and I wouldn't miss them
           | an ounce if they went away.
        
             | handrous wrote:
             | The CAPTCHAs are probably over-applied by people who use
             | the defaults, but they're absolutely necessary for some
             | sites, especially e-commerce. The alternative would be
             | flat-out blocking requests that trigger the CAPTCHAs. An
             | absolute _shitload_ of traffic on the Internet is the
             | abusive sort, and lots of that 's aimed at sites that
             | accept CC payments. Used correctly, CAPTCHAs mean you don't
             | have to blackhole as much traffic, so actually _increase_
             | the fraction of people who can reach your site, versus some
             | other world without them where you 'd just be forced (by
             | costs & risks of dealing with abuse) to drop those
             | requests.
        
               | Nextgrid wrote:
               | If your problem is credit card fraud you can simply
               | enforce 3D Secure (which offloads liability) for requests
               | that are considered risky. The customer can then choose
               | to either use a 3DS-supported card or complete a
               | captcha/etc.
        
             | vonadz wrote:
             | I feel like I've single-handedly trained their AI to
             | identify buses, boats, and planes at this point.
        
               | anamax wrote:
               | I've never gotten planes. Buses and boats are very rare
               | (for me).
               | 
               | I mostly get crosswalks and traffic lights. I
               | occasionally get mountains, motorcycles, and bicycles.
        
               | [deleted]
        
               | vonadz wrote:
               | You don't get them because I've done them all!
        
             | technobabbler wrote:
             | The CAPTCHAs are a per-website setting that individual
             | webmasters set (or, more likely, forget to set).
             | 
             | As an end user, I agree they are annoying. These two things
             | may or may not help (hCaptcha is the engine used by
             | Cloudflare*):
             | 
             | 1) You can set an accessibility cookie that should be good
             | for a while: https://www.hcaptcha.com/accessibility
             | 
             | 2) There is also the Privacy Pass beta, which lets you
             | redeem CAPTCHA solves for "tokens" that can be used for
             | later CAPTCHAs https://www.hcaptcha.com/privacy-pass
             | 
             | But yeah, hCaptcha is really annoying, especially compared
             | to the auto-solve of reCAPTCHA when you're logged in to a
             | Google account.
             | 
             | * Cloudflare switched to hCaptcha in 2020:
             | https://blog.cloudflare.com/moving-from-recaptcha-to-
             | hcaptch...
        
           | technobabbler wrote:
           | > SSL is a solved problem since let's encrypt
           | 
           | Only if you remember to update your cert chains, and your web
           | servers have to keep up with TLS etc. updates too
           | 
           | > cloudflare actually decreases performance (by adding an hop
           | when serving dynamic content).
           | 
           | If your dynamic content doesn't require true real-time
           | updates (like a forum or chat or something), but can be
           | limited to once a minute updates or similar (like a reddit-
           | style front page), caching and global CDNs can still
           | drastically speed that up for users who aren't near your data
           | center.
           | 
           | And that's just their static cache offering. If you build
           | your site around their edge infrastructure (workers, workers
           | KV, durable objects), you can entirely remove the last hop by
           | handling client requests and sharing state across the CDN
           | itself. Two of their demos show IRC-like chat and Doom (the
           | game) running entirely on the edge:
           | https://github.com/cloudflare/workers-chat-demo
           | https://blog.cloudflare.com/doom-multiplayer-workers/
           | 
           | They also do other performance boosts, like auto-optimizing
           | images, converting to webp, minifying stylesheets & scripts,
           | dynamic loading, http QUIC, etc. And they offer a edge
           | streaming solution for video (although Vimeo is probably much
           | cheaper for most use cases).
           | 
           | > For most websites, DDoS attacks are a non-issue.
           | 
           | It can also help with things like Google Analytics bot spam,
           | drive-by vulnerability scans against certain web servers or
           | Wordpress, etc. It's not just a IP blacklist but does some
           | degree of traffic analysis.
           | 
           | And all of that is available for free or cheap. It's very
           | difficult to do all that yourself as a small-biz or solo web
           | dev, even if you had full time dev-ops.
           | 
           | As for "the internet shouldn't be controlled by a single
           | entity", sure, but it's always been a corporate network.
           | Choose your nemesis: Cloudflare, Google, Amazon, Facebook,
           | Verisign/network solutions (in the old days)... there's never
           | been a truly free internet. At least Cloudflare is doing a
           | darned good job of stewarding the internet.
        
           | thefounder wrote:
           | Free DNS, Free CDN, easy to use the user interface, APIs,
           | they use Go
        
           | kentonv wrote:
           | > cloudflare actually decreases performance (by adding an hop
           | when serving dynamic content).
           | 
           | Page load time tends to be dominated by static content.
           | 
           | But even for dynamic content, this isn't necessarily true.
           | Setting up a TLS connection requires multiple network round
           | trips. When using an edge network, those round trips only
           | need to go to the nearest PoP rather than all the way to the
           | server. If the PoP already has connections open to your
           | server (which is probably the case if you have consistent
           | traffic) then the network round trips back to your origin
           | server are avoided, and your dynamic content ends up being
           | served faster.
           | 
           | Additionally, Cloudflare's Argo Smart Routing is often able
           | to route packets across the internet faster than than default
           | network routing, which speeds up the communications between
           | Cloudflare and your origin server.
           | 
           | So it turns out "adding a hop" does not necessarily decrease
           | performance.
           | 
           | (Disclosure: I work for Cloudflare.)
        
             | DaiPlusPlus wrote:
             | > Setting up a TLS connection requires multiple network
             | round trips
             | 
             | QUIC significantly reduces the cost of the TLS handshake, I
             | think now it's only a single additional packet-exchange:
             | https://blog.cloudflare.com/the-road-to-quic/
        
               | tick_tock_tick wrote:
               | Most traffic is not QUIC yet maybe in the future.
        
           | vonadz wrote:
           | For my static site, it substantially decreased loading times
           | compared to when I just host from a VPS.
        
           | DrBenCarson wrote:
           | Your qualification there is important--dynamic content.
           | Static content remains by far the primary source of internet
           | traffic. Streaming video is over 65% of all mobile traffic by
           | volume. That doesn't even account for mobile images.
        
         | stoned wrote:
         | SourceHut and its founder are the promulgators or a never ended
         | stream of strong opinions and principled edicts that do little
         | but alienate people. Drew's solution to every problem is
         | blocking and blackholing [0] which makes him seem weak and
         | petty and suggests that by refusing to work constructively with
         | people he's mostly interested in strongarming and asserting
         | dominance. I find it pretty hard to take him seriously and run
         | from anything he's associated with, even when I agree. There's
         | this concept called "non-violent communication" that he would
         | be well-served to explore.
         | 
         | https://github.com/makeworld-the-better-one/amfora/issues/19...
        
           | vonadz wrote:
           | Promulgators... nice. Saving that in the lexicon for future
           | use.
        
             | stoned wrote:
             | s/promulgators or/promulgators of/
             | 
             | Yeah, it's usually used in the context of the unilateral
             | issuing of decrees.
        
               | vonadz wrote:
               | Sounds as pretentious as what it describes.
        
               | [deleted]
        
           | ectopod wrote:
           | Non-violent communication works if you're talking to an
           | individual as an equal but corporations cannot empathise or
           | be empathised with. It's madness to try.
        
             | [deleted]
        
             | stoned wrote:
             | The open source developer of amfora is about as far as you
             | can get from a corporation, though. And behind every
             | cloudflare reverse proxy connection is a human. Blocking
             | them for nothing other than their choice of Internet route
             | stands antithetical to the foundational spirit of the net,
             | which he is ostensibly trying to protect.
        
       ___________________________________________________________________
       (page generated 2021-11-15 23:01 UTC)