Open nelsonic opened 1 year ago
Supabase
has the concept of an anon
key:
https://supabase.com/docs/guides/database/api#api-url-and-keys
anon
key, which is safe to be used in a browser context."i.e. people are putting these keys in plaintext in their web apps ...
@LuchoTurtle's recent speed-run of the Supabase
+ Flutter
tutorial:
supabase-flutter-demo#42-adding-main-function-and-constants
hard-coded into the demo app: https://github.com/dwyl/supabase-flutter-demo/blob/01a2902fb7a0950cd8af370ea0c1eeaa91e7750d/lib/main.dart#L19-L23
Note: There's an active thread about how to disable
anon
key in theSupabase
discussions: https://github.com/supabase/supabase/discussions/4547 β³ This is not the place to "bash"Supabase
... they have built their system how they see fit. π Instead I want to understand how we can do "anonymous" access toauth
without needing to have ananon
key which IMO is an anti-pattern.
An anon
key encourages people to put the key in-the-clear e.g. in front-end JS
apps.
That means it provides exactly zero security. 0οΈβ£
So what's the point of having it? π€·ββοΈ
OK, I've thought about this a lot from both the security and usability perspectives. π
Crucially, if we're building a Native App
using Flutter
, π±
and there isn't a way to protect an API key in Flutter
, see: https://github.com/dwyl/learn-flutter/issues/82 π
So while
we aren't going to completely remove the AUTH_API_KEY
,
we are going to re-think it as "non-secure". π
i.e. we won't use it as a "key" but rather as an "identifier". π -> π€
The key [breaking] change we will be making to the AUTH_API_KEY
is the format:
auth.domain.com/:person_id/:public_key
Before:
88SwQD4YweF8q7iAt1RPVjwqnztrEP9Lm4XWn/88SwQGcsdq4gUpR9D69DFAXyZep/authdemo.fly.dev
After:
authdemo.fly.dev/88SwQD4YweF8q7iAt1RPVjwqnztrEP9Lm4XWn/88SwQGcsdq4gUpR9D69DFAXyZep
The change is pretty basic; on the surface ...
Instead of having the URL
as the last part of the AUTH_API_KEY
,
it will be at the start of the AUTH_API_KEY
.
But rather than this being a boring key, it will also be a functional URL/endpoint.
i.e. visiting: authdemo.fly.dev/88SwQD4YweF8q/88SwQGcsdq4g
in a browser will show the info/stats for the client - provided you successfully authenticate.
As previously noted, this is a breaking change so we will need to release a V2
of auth_plug
.
We're going to make it explicit in all our docs that the AUTH_API_KEY
does not contain anything sensitive
and can safely be embedded in a front-end/Native App. The only reason to continue using environment variables to specify the key is to be able to switch between auth
instances
e.g: from authdemo.fly.dev
to auth.dwyl.com
or auth.acme.co
I think this is as simple as we can make it.
We're always going to need an auth
instance URL
so the App
knows where to send people to authenticate.
So the next question is: should we rename our SingleEnvironmentVariableTM
from AUTH_API_KEY
to AUTH_URL
for clarity/simplicity
given that it will in fact be just a URL
not an "API Key"...? π
I agree with the changes. However, even though this following question might be me missing something...
I wonder if, even though the AUTH_URL
is an identifier and not a key, can't it be used to impersonate other people, since the AUTH_URL
is accessible by anyone in the browser?
AUTH_URL
will be restricted to the person that is allowed to see it. π
I will attempt to clarify this shortly. π€
But yes, you're right. perhaps the the AUTH_API_KEY
name will be clearer to people
... π
If the AUTH_API_KEY
is left in-the-clear, e.g. committed to GitHub
by mistake,
it could be used to authenticate by someone that isn't the owner.
This is the same as leaking any other API Key
by committing it to GitHub
.
The mitigation will be:
a) Having an "Allowed List" for the URL
that is allowed authenticate. i.e. only app.dwyl.com
https://github.com/dwyl/auth/issues/281
b) Additional check on a new
device, i.e: for people authenticating on a new phone/computer they will have to verify via 2nd factor auth. TBD
Continuing on from our discussion in: https://github.com/dwyl/auth/issues/268 and with the benefit of our knowledge from
Flutter
andJS
-land ... Trying to think aboutauth
from first principals ... How are we going to enableauth
in ourFlutter
app with the least code possible and without the need for keeping "secrets" ... πWhy do we have an
AUTH_API_KEY
in the first place?We (I) created an
AUTH_API_KEY
because I thought that it was needed for identifying/verifying whichApp
is usingauth
for authenticating the person. But when I think about it with my beginner's mind I'm forced to think "Why...?" π€·ββοΈIf someone is running a
Phoenix
App onlocalhost
then we know they are in "Dev" mode, right? π©βπ» So why do they need to have anAUTH_API_KEY
to identify them? π€ TheAUTH_API_KEY
doesn't provide theperson
using theapp
any additional security it's just an extra step for the Dev/Engineer to setup ...Does
auth
need anAPI_KEY
or can we just do domain-based verification? πCan we just create an "Allowed List" for urls that are allowed to use
auth
and reject any other URL? We currently require theURL
to be defined for anapp
, e.g: https://auth.dwyl.com/apps/45If we are doing a domain-based verification, then do we need an
AUTH_API_KEY
? π What real additional security is theAUTH_API_KEY
giving us? Is it just perceived security because we've been trained to think thatAPI Keys
are the "right" way to do this? π€How will an attacker exploit a system that only has domain-based verification?
Hypothetically, if we were to completely remove the
AUTH_API_KEY
, how would a malicious person ("attacker") attempt to use ourauth
system to get people to login with their Google/GitHub/etc account and steal their data? πIf the attacker can intercept a request or create a fake page that looks like our
App
, and use our ownauth
endpoint to authenticate aperson
and then replay the successfulJWT
back to theApp
they can read theperson's
data ...How can we do domain-based verification on a Distributed App?
If our
Flutter App
is web-based or deployed to theApp/Play Store
, will there be a "domain" for it? π And if there is no domain associated with the "Native" App, how do we verify it? π€·ββοΈ Is there a unique string associated with theiOS
orAndroid
build that cannot be spoofed?These are the questions that are on my mind right now as I'm thinking about
auth
in general and specifically gearing up to re-writeauth
from first principals to be an order of magnitude simpler.