-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support Sign in With Apple #4
Comments
In a normal SIWA token exchange, the app sends the access token and identity token to the server. Then, the server validates the identity token and stores the access token for later use. Then, instead of using the Apple JWT, you're supposed to sign and send back a custom JWT and access token for your own server. Apple's JWTs only last 24 hours, so it's built to be like that. Then if the server needs to update or request user info it uses the access token to ask Apple for that info. The SIWA JWT is only used for the original user sign in. Right now I think the GoTrue server would need to be modified to accept and validate the JWT from the I was also looking at the |
So do we need to move the issue to server component? |
Yeah I think we do, once they add an endpoint we can add it to the swift repo. We should also test using the existing |
Actually scratch that, we'd need support for sending a Sadly I don't have enough experience in Go to make sense of the server library I'll make an issue there and reference this. |
supabase/auth#189 |
Any updates? |
I had the same question. I'm starting on an app that supports Sign In With Apple and only now discovered that SIWA isn't supported. Not meaning to pressure y'all but is there an estimate on when SIWA could work? |
I’ve done apple stuff before a few times - perhaps we could compare notes and make a self hosted nodejs apple sign in / express passport with JavaScript that updates the auth.users table instead of being blocked here. It’s a bit crap but need to ship the app. Note - a lot of the javascript is specific to browser stuff / my approach is using nodejs below and it does not have a user / session. The critical distinction in flows - native login on server can use grant_type authorization_code (this is different to web callback url / access_tokens that webflow uses) SERVER - nodejs on ec2 - (ideally this would be supported on supabase) const params = {
grant_type: 'authorization_code', // refresh_token authorization_code
code: req.body.code,
redirect_uri: config.apple.redirectURI,
client_id: config.apple.clientID,
client_secret: clientSecret,
// refresh_token:req.body.id_token
}
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
data: qs.stringify(params),
url: 'https://appleid.apple.com/auth/token' -> here we get back an authorization.code - on swift app (see sample repo below) if let code = appleCredential.authorizationCode {
let authCode = String(data: code, encoding: .utf8)!
loginWithApple( authCode) // send this code to our nodejs -> create the user / or login / return supabase jwt.
} in essense some psuedocode STEP 1:
A) if no account exists on system (google / firebase / facebook / apple / snapchat) - create a new one const returnExistingSupabaseJWTorCreateAccount = async (jwtClaims) => {
let user = await findExistingUserByEmail(jwtClaims.email);
{
const { data: response, error } = await supabase.auth.admin.listUsers();
// console.log("listUsers response:", response.users);
for await (let u of response.users) {
if (u.id == user.id) {
console.log("we found existing user in supabase:", u);
}
}
}
if (user == null) {
console.log("🌱 creating user");
const { data: newUser, error } = await supabase.auth.admin.createUser({
email: jwtClaims.email,
email_confirm: true // missing provide / identities guff
})
console.log("newUser:", newUser);
} else {
console.log("🌱 we found a gotrue user:",user);
// create an access token - this needs more work - or port to golang
let claims = {
"StandardClaims": {
"sub": user.id,
"aud": "",
"exp": Math.floor(Date.now() / 1000),
},
"Email": user.Email,
"AppMetaData": user.AppMetaData,
"UserMetaData": user.UserMetaData,
}
console.log("✅ claims:", claims);
const jwt = sign(claims, config.supabase.jwtSecret); // needs testing
console.log("jwt:", jwt);
return jwt;
}
}
additional notes - supabase/auth#451 UPDATE: I've made sample project ( follow along here) This needs more work - Once authorization code is verified - we can dig up the the apple jwt claims (though we may need to pass apple email for email) const jwtClaims = { iss: 'https://appleid.apple.com',
aud: 'app.test.ios',
exp: 1579483805,
iat: 1579483205,
sub: '000317.c7d501c4f43c4a40ac3f79e122336fcf.0952',
at_hash: 'G413OYB2Ai7UY5GtiuG68A',
email: '[email protected]',
email_verified: 'true',
is_private_email: 'true',
auth_time: 1579483204 } here we get a response from apple (jwtClaims) - and return a jwt(supabase) referening auth.user code in my sample repo uses the supabase.admin.createuser - INSERT INTO
auth.users (
id,
instance_id,
ROLE,
aud,
email,
raw_app_meta_data,
raw_user_meta_data,
is_super_admin,
encrypted_password,
created_at,
updated_at,
last_sign_in_at,
email_confirmed_at,
confirmation_sent_at,
confirmation_token,
recovery_token,
email_change_token_new,
email_change
)
VALUES
(
gen_random_uuid(),
'00000000-0000-0000-0000-000000000000',
'authenticated',
'authenticated',
'[email protected]',
'{"provider":"email","providers":["email"]}',
'{}',
FALSE,
crypt('Pa55word!', gen_salt('bf')),
NOW(),
NOW(),
NOW(),
NOW(),
NOW(),
'',
'',
'',
''
);
INSERT INTO
auth.identities (
id,
provider,
user_id,
identity_data,
last_sign_in_at,
created_at,
updated_at
)
VALUES
(
(
SELECT
id
FROM
auth.users
WHERE
email = '[email protected]'
),
'email',
(
SELECT
id
FROM
auth.users
WHERE
email = '[email protected]'
),
json_build_object(
'sub',
(
SELECT
id
FROM
auth.users
WHERE
email = '[email protected]'
)
),
NOW(),
NOW(),
NOW()
);
N.B. - I have the webflow sign in working using client_secret.rb in my repo ( this is not what I want) this is apple's latest sample sign in code - can download here UPDATE: we can use then post this to the nodejs server - and get the supabase jwt. Problem I have is this isn't a legitimate jwt. NOTEs - when using the client_secret - webflow - the identity is correctly stored using the gotrue flows. I need to either get gotrue to support this authorization flow upstream - or we need craft this to insert ```javascript// I need to
|
Any update on having this fixed to work with "Sign in with Apple" workflow, or is this still a partially server-side issue that needs a broader look? |
I'm wondering if this is a more complete fit - https://next-auth.js.org/adapters/supabase = still need the nodejs server - but using this adapter - maybe more elegant than hacking with postgres injection.... |
Hello any updates? This issue has been opened in 2021... any ETA on when this would be fixed? |
Bumping this. Any updates from the supabase team? cc @thecoolwinter |
@kangmingtay - is there anyway we can progress this? |
Hi @johndpope, apologies for the late reply, this should be possible via the You'll need to add your IOS Bundle ID in the dashboard's auth settings under the apple provider -> "Services ID". We're looking to add the "IOS Bundle ID" as a field in the dashboard as well so that we can support both mobile & web logins through apple. As this is a pretty long thread, i just wanted to make sure i'm understanding the issue correctly: We want to be able to use native apple authentication with swift for SIWA. Using something like Apple Authentication Services would be ideal for the iOS App Store reviews and also provides a nice native experience for the user rather than redirecting them to a web browser if you use |
at first glance - it doesn't seem adequate - I want this app to sign into supabase - using swift - natively. the successful authorization code we get back from apple looks like this it's not a json web token. I can see it's possible to perhaps craft this to fit your suggestion - but...
when I hit the backend in javascript / passport / node for my approach - this is apple / nodejs passport sample node when I search supbase codebase for this is the heart of how the backend - gotrue should go outbound with above authorization code - and either create user / or login and return the jwt. please help - I want this fixed. If you can take the above sample apple code - and hack to use the token approach - I'm also call with that. // BACKEND - APPLE LOGIN
// https://developer.apple.com/documentation/signinwithapplerestapi/generate_and_validate_tokens
// const url = new URL(`https://appleid.apple.com/auth/authorize?scope=name%20email&client_id=${appleid.client_id}&redirect_uri=${redirectUri}&response_type=code%20id_token&response_mode=form_post`)
const getAuthorizationUrl = () => {
const url = new URL('https://appleid.apple.com/auth/authorize');
url.searchParams.append('response_type', 'code id_token');
url.searchParams.append('response_mode', 'form_post');
url.searchParams.append('client_id', config.apple.clientID);
url.searchParams.append('redirect_uri', config.apple.redirectURI);
url.searchParams.append('scope', 'name,email');
return url.toString();
}; UPDATE |
Hi @johndpope, i think you'll need to complete the authorization code flow with swift natively first. You should get back an id token as mentioned in the link you provided: https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens This id token can then be used in
Yeah just confirmed that that's unfortunately the case :/ the swift library for gotrue is community maintained and as such, it seems to have fallen behind the JS and Flutter client libs. You're welcome to make a contribution to the library to add the Also, just looping in @maail here who's helping us out with the swift community library in case he has the bandwidth to pick this up :) |
ok - this looks very doable /// - Tag: did_complete_authorization
func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
switch authorization.credential {
case let appleIDCredential as ASAuthorizationAppleIDCredential:
if let token = appleIDCredential.identityToken{
print("token:",token);
// TODO - call the signInWithIdToken endpoint
}
// if let authCode = appleIDCredential.authorizationCode{
// print("authorizationCode:",authCode);
// if let authCodeStr = String(data:authCode,encoding: .utf8){
// loginWithApple(authCodeStr);
// }
// }
UPDATE UPDATE 2 - good news - it's working ✅ @catlan - you can close this ticket. @GRSouza / @maail - it would be good to have this apple signin code in this repo to demonstrate sign in + assigning access token to auth credentials for the supabase client. |
Feel free to open a new issue if needed. |
Feature request
Following on the thread in supabase/supabase#1882 and supabase/supabase#2805 I looked into adding support for AuthenticationServices and in this regard ASAuthorizationAppleIDCredential.
Is your feature request related to a problem? Please describe.
Describe the solution you'd like
I started work on this here: https://github.com/catlan/gotrue-swift/commit/bac99073ad56ce6fa3257f33a22a628a135e0e9a
The problem is that the response I get:
"Invalid token: signing method RS256 is invalid"
I'm not too familiar with either Sign in With Apple nor supabase. Any clues on what is required to make this work?
The text was updated successfully, but these errors were encountered: