Initial push
This commit is contained in:
115
siwa/api/siwa.script_api
Normal file
115
siwa/api/siwa.script_api
Normal file
@@ -0,0 +1,115 @@
|
||||
- name: siwa
|
||||
type: table
|
||||
desc: Functions and constants for interacting Sign in with Apple.
|
||||
[icon:ios]
|
||||
members:
|
||||
|
||||
#*****************************************************************************************************
|
||||
|
||||
- name: is_supported
|
||||
type: function
|
||||
desc: Check if Sign in with Apple is available (iOS 13+).
|
||||
|
||||
|
||||
#*****************************************************************************************************
|
||||
|
||||
- name: get_credential_state
|
||||
type: function
|
||||
desc: Get the credential state of a user.
|
||||
|
||||
parameters:
|
||||
- name: user_id
|
||||
type: string
|
||||
desc: User id to get credential state for.
|
||||
- name: callback
|
||||
type: function
|
||||
desc: Credential state callback function.
|
||||
parameters:
|
||||
- name: self
|
||||
type: object
|
||||
desc: The current object.
|
||||
|
||||
- name: state
|
||||
type: table
|
||||
desc: The credential state (user_id, credential_state)
|
||||
|
||||
examples:
|
||||
- desc: |-
|
||||
```lua
|
||||
siwa.get_credential_state(id, function(self, data)
|
||||
if data.credential_state == siwa.STATE_AUTHORIZED then
|
||||
print("User has still authorized the application", data.user_id)
|
||||
elseif data.credential_state == siwa.STATE_REVOKED then
|
||||
print("User has revoked authorization for the application", data.user_id)
|
||||
end
|
||||
end)
|
||||
```
|
||||
|
||||
#*****************************************************************************************************
|
||||
|
||||
- name: authenticate
|
||||
type: function
|
||||
desc: Show the Sign in with Apple UI
|
||||
|
||||
parameters:
|
||||
- name: callback
|
||||
type: function
|
||||
desc: Authentication callback function.
|
||||
parameters:
|
||||
- name: self
|
||||
type: object
|
||||
desc: The current object.
|
||||
|
||||
- name: state
|
||||
type: table
|
||||
desc: The authentication result data (user_id, identity_token, email, first_name, family_name, status, result)
|
||||
|
||||
examples:
|
||||
- desc: |-
|
||||
```lua
|
||||
siwa.authenticate(function(self, data)
|
||||
print(data.identity_token)
|
||||
print(data.user_id)
|
||||
print(data.first_name, data.family_name)
|
||||
print(data.email)
|
||||
if data.user_status == siwa.STATUS_LIKELY_REAL then
|
||||
print("Likely a real person")
|
||||
end
|
||||
end)
|
||||
```
|
||||
|
||||
#*****************************************************************************************************
|
||||
|
||||
- name: STATE_NOT_FOUND
|
||||
type: number
|
||||
desc: The user can’t be found.
|
||||
|
||||
|
||||
- name: STATE_UNKNOWN
|
||||
type: number
|
||||
desc: Unknown credential state.
|
||||
|
||||
|
||||
- name: STATE_AUTHORIZED
|
||||
type: number
|
||||
desc: The user is authorized.
|
||||
|
||||
|
||||
- name: STATE_REVOKED
|
||||
type: number
|
||||
desc: Authorization for the given user has been revoked.
|
||||
|
||||
|
||||
- name: STATUS_UNKNOWN
|
||||
type: number
|
||||
desc: The system hasn’t determined whether the user might be a real person.
|
||||
|
||||
|
||||
- name: STATUS_UNSUPPORTED
|
||||
type: number
|
||||
desc: The system can’t determine this user’s status as a real person.
|
||||
|
||||
|
||||
- name: STATUS_LIKELY_REAL
|
||||
type: number
|
||||
desc: The user appears to be a real person.
|
30
siwa/ext.manifest
Executable file
30
siwa/ext.manifest
Executable file
@@ -0,0 +1,30 @@
|
||||
name: siwa
|
||||
|
||||
platforms:
|
||||
x86-osx:
|
||||
context:
|
||||
frameworks: []
|
||||
flags: ["-std=c++11", "-stdlib=libc++"]
|
||||
linkFlags: ["-stdlib=libc++"]
|
||||
libs: ["c++"]
|
||||
|
||||
x86_64-osx:
|
||||
context:
|
||||
frameworks: []
|
||||
flags: ["-std=c++11", "-stdlib=libc++"]
|
||||
libs: ["c++"]
|
||||
|
||||
x86_64-ios:
|
||||
context:
|
||||
frameworks: ['AuthenticationServices']
|
||||
defines: ['SUPPORTS_SIWA']
|
||||
|
||||
armv7-ios:
|
||||
context:
|
||||
frameworks: ['AuthenticationServices']
|
||||
defines: ['SUPPORTS_SIWA']
|
||||
|
||||
arm64-ios:
|
||||
context:
|
||||
frameworks: ['AuthenticationServices']
|
||||
defines: ['SUPPORTS_SIWA']
|
292
siwa/src/siwa.cpp
Executable file
292
siwa/src/siwa.cpp
Executable file
@@ -0,0 +1,292 @@
|
||||
#if defined(DM_PLATFORM_IOS)
|
||||
|
||||
#include "siwa.h"
|
||||
#include <dmsdk/sdk.h>
|
||||
|
||||
#define MODULE_NAME "siwa"
|
||||
|
||||
SiwaData g_SiwaData;
|
||||
SiwaCallbackData g_SiwaCallbackData;
|
||||
|
||||
char* Siwa_GetUserId()
|
||||
{
|
||||
return g_SiwaData.m_userID;
|
||||
}
|
||||
|
||||
static void Siwa_ResetCallbackData()
|
||||
{
|
||||
free(g_SiwaCallbackData.m_userID);
|
||||
g_SiwaCallbackData.m_userID = 0;
|
||||
free(g_SiwaCallbackData.m_identityToken);
|
||||
g_SiwaCallbackData.m_identityToken = 0;
|
||||
free(g_SiwaCallbackData.m_userID);
|
||||
g_SiwaCallbackData.m_userID = 0;
|
||||
free(g_SiwaCallbackData.m_email);
|
||||
g_SiwaCallbackData.m_email = 0;
|
||||
free(g_SiwaCallbackData.m_firstName);
|
||||
g_SiwaCallbackData.m_firstName = 0;
|
||||
free(g_SiwaCallbackData.m_familyName);
|
||||
g_SiwaCallbackData.m_familyName = 0;
|
||||
free(g_SiwaCallbackData.m_identityToken);
|
||||
g_SiwaCallbackData.m_identityToken = 0;
|
||||
free(g_SiwaCallbackData.m_message);
|
||||
g_SiwaCallbackData.m_message = 0;
|
||||
|
||||
g_SiwaCallbackData.m_userStatus = STATUS_UNSUPPORTED;
|
||||
g_SiwaCallbackData.m_state = STATE_UNKNOWN;
|
||||
g_SiwaCallbackData.m_cmd = CMD_NONE;
|
||||
}
|
||||
|
||||
void Siwa_QueueCredentialCallback(const char* userID, const SiwaCredentialState state)
|
||||
{
|
||||
if(g_SiwaCallbackData.m_cmd != CMD_NONE) {
|
||||
dmLogError("Can't queue credential callback, already have a callback queued!");
|
||||
return;
|
||||
}
|
||||
|
||||
g_SiwaCallbackData.m_cmd = CMD_CREDENTIAL;
|
||||
g_SiwaCallbackData.m_userID = strdup(userID);
|
||||
g_SiwaCallbackData.m_state = state;
|
||||
}
|
||||
|
||||
|
||||
void Siwa_QueueAuthSuccessCallback(const char* identityToken, const char* userID, const char* email, const char* firstName, const char* familyName, const SiwaUserDetectionStatus userStatus)
|
||||
{
|
||||
if(g_SiwaCallbackData.m_cmd != CMD_NONE) {
|
||||
dmLogError("Can't queue auth success callback, already have a callback queued!");
|
||||
return;
|
||||
}
|
||||
|
||||
g_SiwaCallbackData.m_cmd = CMD_AUTH_SUCCESS;
|
||||
g_SiwaCallbackData.m_identityToken = strdup(identityToken);
|
||||
g_SiwaCallbackData.m_userID = strdup(userID);
|
||||
g_SiwaCallbackData.m_email = strdup(email != 0 ? email: "");
|
||||
g_SiwaCallbackData.m_firstName = strdup(firstName != 0 ? firstName: "");
|
||||
g_SiwaCallbackData.m_familyName = strdup(familyName != 0 ? familyName : "");
|
||||
g_SiwaCallbackData.m_userStatus = userStatus;
|
||||
g_SiwaCallbackData.m_message = strdup("");
|
||||
}
|
||||
|
||||
void Siwa_QueueAuthFailureCallback(const char* message)
|
||||
{
|
||||
if(g_SiwaCallbackData.m_cmd != CMD_NONE) {
|
||||
dmLogError("Can't queue auth error callback, already have a callback queued!");
|
||||
return;
|
||||
}
|
||||
|
||||
g_SiwaCallbackData.m_cmd = CMD_AUTH_FAILED;
|
||||
g_SiwaCallbackData.m_message = strdup(message);
|
||||
}
|
||||
|
||||
|
||||
static void Siwa_TriggerCallback()
|
||||
{
|
||||
lua_State* L = dmScript::GetCallbackLuaContext(g_SiwaData.m_callback);
|
||||
DM_LUA_STACK_CHECK(L, 0);
|
||||
|
||||
if (dmScript::SetupCallback(g_SiwaData.m_callback))
|
||||
{
|
||||
lua_createtable(L, 0, 3);
|
||||
|
||||
if (g_SiwaCallbackData.m_cmd == CMD_CREDENTIAL)
|
||||
{
|
||||
lua_pushstring(L, "result");
|
||||
lua_pushstring(L, "SUCCESS");
|
||||
lua_settable(L, -3);
|
||||
|
||||
lua_pushstring(L, "user_id");
|
||||
lua_pushstring(L, g_SiwaCallbackData.m_userID);
|
||||
lua_settable(L, -3);
|
||||
|
||||
lua_pushstring(L, "credential_state");
|
||||
lua_pushnumber(L, g_SiwaCallbackData.m_state);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
else if (g_SiwaCallbackData.m_cmd == CMD_AUTH_SUCCESS)
|
||||
{
|
||||
lua_pushstring(L, "result");
|
||||
lua_pushstring(L, "SUCCESS");
|
||||
lua_settable(L, -3);
|
||||
|
||||
lua_pushstring(L, "identity_token");
|
||||
lua_pushstring(L, g_SiwaCallbackData.m_identityToken);
|
||||
lua_settable(L, -3);
|
||||
|
||||
lua_pushstring(L, "user_id");
|
||||
lua_pushstring(L, g_SiwaCallbackData.m_userID);
|
||||
lua_settable(L, -3);
|
||||
|
||||
lua_pushstring(L, "email");
|
||||
lua_pushstring(L, g_SiwaCallbackData.m_email);
|
||||
lua_settable(L, -3);
|
||||
|
||||
lua_pushstring(L, "first_name");
|
||||
lua_pushstring(L, g_SiwaCallbackData.m_firstName);
|
||||
lua_settable(L, -3);
|
||||
|
||||
lua_pushstring(L, "family_name");
|
||||
lua_pushstring(L, g_SiwaCallbackData.m_familyName);
|
||||
lua_settable(L, -3);
|
||||
|
||||
lua_pushstring(L, "user_status");
|
||||
lua_pushnumber(L, g_SiwaCallbackData.m_userStatus);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
else if (g_SiwaCallbackData.m_cmd == CMD_AUTH_FAILED)
|
||||
{
|
||||
lua_pushstring(L, "result");
|
||||
lua_pushstring(L, "ERROR");
|
||||
lua_settable(L, -3);
|
||||
|
||||
lua_pushstring(L, "message");
|
||||
lua_pushstring(L, g_SiwaCallbackData.m_message);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
|
||||
if (lua_pcall(L, 2, 0, 0) != 0)
|
||||
{
|
||||
dmLogError("Error running siwa callback: %s", lua_tostring(L, -1));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
dmScript::TeardownCallback(g_SiwaData.m_callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void Siwa_SetupCallback(lua_State* L, int index)
|
||||
{
|
||||
if (g_SiwaData.m_callback) {
|
||||
dmScript::DestroyCallback(g_SiwaData.m_callback);
|
||||
}
|
||||
g_SiwaData.m_callback = dmScript::CreateCallback(L, index);
|
||||
}
|
||||
|
||||
static void Siwa_CleanupCallback() {
|
||||
if (g_SiwaData.m_callback) {
|
||||
dmScript::DestroyCallback(g_SiwaData.m_callback);
|
||||
g_SiwaData.m_callback = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int Siwa_GetCredentialState(lua_State* L){
|
||||
DM_LUA_STACK_CHECK(L, 1);
|
||||
|
||||
if (!Siwa_PlatformIsSupported()) {
|
||||
dmLogWarning("Sign in with Apple is not available");
|
||||
lua_pushboolean(L, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(g_SiwaData.m_callback != 0)
|
||||
{
|
||||
dmLogError("Callback already in progress");
|
||||
lua_pushboolean(L, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
luaL_checktype(L, 1, LUA_TSTRING);
|
||||
if (g_SiwaData.m_userID) free(g_SiwaData.m_userID);
|
||||
g_SiwaData.m_userID = strdup(lua_tostring(L, 1));
|
||||
|
||||
luaL_checktype(L, 2, LUA_TFUNCTION);
|
||||
Siwa_SetupCallback(L, 2);
|
||||
Siwa_PlatformGetCredentialState();
|
||||
|
||||
lua_pushboolean(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int Siwa_AuthenticateWithApple(lua_State* L) {
|
||||
DM_LUA_STACK_CHECK(L, 1);
|
||||
|
||||
if (!Siwa_PlatformIsSupported()) {
|
||||
dmLogWarning("Sign in with Apple is not available");
|
||||
lua_pushboolean(L, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(g_SiwaData.m_callback != 0)
|
||||
{
|
||||
dmLogError("Callback already in progress");
|
||||
lua_pushboolean(L, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
luaL_checktype(L, 1, LUA_TFUNCTION);
|
||||
Siwa_SetupCallback(L, 1);
|
||||
Siwa_PlatformAuthenticateWithApple();
|
||||
|
||||
lua_pushboolean(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int Siwa_IsSupported(lua_State* L) {
|
||||
DM_LUA_STACK_CHECK(L, 1);
|
||||
lua_pushboolean(L, Siwa_PlatformIsSupported());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static dmExtension::Result SiwaAppInitialize(dmExtension::AppParams* params)
|
||||
{
|
||||
Siwa_ResetCallbackData();
|
||||
return dmExtension::RESULT_OK;
|
||||
}
|
||||
|
||||
static dmExtension::Result SiwaAppFinalize(dmExtension::AppParams* params)
|
||||
{
|
||||
return dmExtension::RESULT_OK;
|
||||
}
|
||||
|
||||
const luaL_reg lua_register[] =
|
||||
{
|
||||
{"is_supported", Siwa_IsSupported},
|
||||
{"get_credential_state", Siwa_GetCredentialState},
|
||||
{"authenticate", Siwa_AuthenticateWithApple},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
static dmExtension::Result SiwaInitialize(dmExtension::Params* params)
|
||||
{
|
||||
lua_State* L = params->m_L;
|
||||
int top = lua_gettop(L);
|
||||
luaL_register(L, MODULE_NAME, lua_register);
|
||||
|
||||
#define SETCONSTANT(name) \
|
||||
lua_pushnumber(L, (lua_Number) name); \
|
||||
lua_setfield(L, -2, #name);\
|
||||
|
||||
SETCONSTANT(STATE_NOT_FOUND)
|
||||
SETCONSTANT(STATE_UNKNOWN)
|
||||
SETCONSTANT(STATE_AUTHORIZED)
|
||||
SETCONSTANT(STATE_REVOKED)
|
||||
|
||||
SETCONSTANT(STATUS_UNKNOWN)
|
||||
SETCONSTANT(STATUS_UNSUPPORTED)
|
||||
SETCONSTANT(STATUS_LIKELY_REAL)
|
||||
|
||||
#undef SETCONSTANT
|
||||
|
||||
lua_pop(L, 1);
|
||||
assert(top == lua_gettop(L));
|
||||
return dmExtension::RESULT_OK;
|
||||
}
|
||||
|
||||
static dmExtension::Result SiwaUpdate(dmExtension::Params* params)
|
||||
{
|
||||
if(g_SiwaCallbackData.m_cmd != CMD_NONE)
|
||||
{
|
||||
Siwa_TriggerCallback();
|
||||
Siwa_ResetCallbackData();
|
||||
Siwa_CleanupCallback();
|
||||
}
|
||||
return dmExtension::RESULT_OK;
|
||||
}
|
||||
|
||||
static dmExtension::Result SiwaFinalize(dmExtension::Params* params)
|
||||
{
|
||||
return dmExtension::RESULT_OK;
|
||||
}
|
||||
|
||||
DM_DECLARE_EXTENSION(siwa, MODULE_NAME, SiwaAppInitialize, SiwaAppFinalize, SiwaInitialize, SiwaUpdate, 0, SiwaFinalize);
|
||||
|
||||
#endif
|
86
siwa/src/siwa.h
Executable file
86
siwa/src/siwa.h
Executable file
@@ -0,0 +1,86 @@
|
||||
#pragma once
|
||||
#if defined(DM_PLATFORM_IOS)
|
||||
|
||||
#include <dmsdk/sdk.h>
|
||||
|
||||
enum SiwaCallbackCmd
|
||||
{
|
||||
CMD_NONE = 0,
|
||||
CMD_CREDENTIAL = 1,
|
||||
CMD_AUTH_SUCCESS = 2,
|
||||
CMD_AUTH_FAILED = 3
|
||||
};
|
||||
|
||||
// https://developer.apple.com/documentation/authenticationservices/asauthorizationappleidprovidercredentialstate/asauthorizationappleidprovidercredentialauthorized?language=objc
|
||||
enum SiwaCredentialState
|
||||
{
|
||||
STATE_UNKNOWN = 0,
|
||||
STATE_AUTHORIZED = 1,
|
||||
STATE_REVOKED = 2,
|
||||
STATE_NOT_FOUND = 3
|
||||
};
|
||||
|
||||
// https://developer.apple.com/documentation/authenticationservices/asuserdetectionstatus?language=objc
|
||||
enum SiwaUserDetectionStatus
|
||||
{
|
||||
STATUS_UNSUPPORTED = 0,
|
||||
STATUS_LIKELY_REAL = 1,
|
||||
STATUS_UNKNOWN = 2
|
||||
};
|
||||
|
||||
struct SiwaCallbackData
|
||||
{
|
||||
SiwaCallbackData()
|
||||
{
|
||||
memset(this, 0, sizeof(*this));
|
||||
};
|
||||
|
||||
SiwaCallbackCmd m_cmd;
|
||||
SiwaCredentialState m_state;
|
||||
SiwaUserDetectionStatus m_userStatus;
|
||||
|
||||
char* m_identityToken;
|
||||
char* m_userID;
|
||||
char* m_email;
|
||||
char* m_firstName;
|
||||
char* m_familyName;
|
||||
|
||||
char* m_message;
|
||||
};
|
||||
|
||||
struct SiwaData
|
||||
{
|
||||
SiwaData()
|
||||
{
|
||||
memset(this, 0, sizeof(*this));
|
||||
};
|
||||
|
||||
// the user ID used for checking credential state
|
||||
char* m_userID;
|
||||
|
||||
dmScript::LuaCallbackInfo* m_callback;
|
||||
};
|
||||
|
||||
char* Siwa_GetUserId();
|
||||
|
||||
// Queue the credential check callback to be triggered next update call in the main thread.
|
||||
void Siwa_QueueCredentialCallback(const char* userID, const SiwaCredentialState state);
|
||||
// Queue the sign in authorization callback to be triggered next update call in the main thread, when authorization succeeds.
|
||||
void Siwa_QueueAuthSuccessCallback(const char* identityToken, const char* userID, const char* email, const char* firstName, const char* familyName, const SiwaUserDetectionStatus userStatus);
|
||||
// Queue the sign in authorization callback to be triggered next update call in the main thread, when authorization fails.
|
||||
void Siwa_QueueAuthFailureCallback(const char* message);
|
||||
|
||||
// Trigged by a call from lua to check if sign in with apple is supported on this device.
|
||||
bool Siwa_PlatformIsSupported();
|
||||
|
||||
// Triggered by a call from lua to start the sign in with apple flow
|
||||
// expects the callback to be a reference number to the lua registry
|
||||
// expects the context to be reference number to the lua registry
|
||||
void Siwa_PlatformAuthenticateWithApple();
|
||||
|
||||
// Triggered by a call from lua to check if a provided apple id grants this app permission to use that id.
|
||||
// expects the callback to be a reference number to the lua registry
|
||||
// expects the context to be reference number to the lua registry
|
||||
void Siwa_PlatformGetCredentialState();
|
||||
|
||||
#endif
|
184
siwa/src/siwa_ios.mm
Executable file
184
siwa/src/siwa_ios.mm
Executable file
@@ -0,0 +1,184 @@
|
||||
#if defined(DM_PLATFORM_IOS)
|
||||
|
||||
#include "siwa.h"
|
||||
|
||||
#include <AuthenticationServices/AuthenticationServices.h>
|
||||
|
||||
#include <dmsdk/sdk.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
// The sign in with Apple flow expects us to have a delegate to which it can both pass data from the sign in flow
|
||||
// but also how to figure out in which UI context it should display the native login UI.
|
||||
// This class is that delegate.
|
||||
// It also owns the provider that is both used for the sign in flow, as well as for credential state checking.
|
||||
API_AVAILABLE(ios(13.0))
|
||||
@interface SiwaManager : NSObject <ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding>
|
||||
@property (nonatomic, strong) ASAuthorizationAppleIDProvider *m_idProvider;
|
||||
@end
|
||||
|
||||
@implementation SiwaManager
|
||||
|
||||
- (instancetype) init
|
||||
{
|
||||
self = [super init];
|
||||
if (self)
|
||||
{
|
||||
self.m_idProvider = [[ASAuthorizationAppleIDProvider alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
// Check if the user id provided to use from lua still grants our app permission
|
||||
// to use it for sign in. User's can revoke app's permissions to use the id for sign in
|
||||
// at any time, so we need to be able to monitor this.
|
||||
// The possible results are revoked(0), authorized(1), and unknown(2).
|
||||
// In practice, we have recieved unknown when revoking permission to this test app
|
||||
// so we should treat both revoked and unknown as unauthorized.
|
||||
- (void) getCredentialState
|
||||
{
|
||||
char* userId = Siwa_GetUserId();
|
||||
NSString* user_id_string = [[NSString alloc] initWithUTF8String:userId];
|
||||
|
||||
[self.m_idProvider getCredentialStateForUserID: user_id_string
|
||||
completion: ^(ASAuthorizationAppleIDProviderCredentialState credentialState, NSError* error) {
|
||||
|
||||
// TODO: docs provide no information about what type of errors we can expect:
|
||||
// https://developer.apple.com/documentation/authenticationservices/asauthorizationappleidprovider/3175423-getcredentialstateforuserid?language=objc
|
||||
if (error) {
|
||||
NSString *errorMessage = [NSString stringWithFormat: @"getCredentialStateForUserID completed with error: %@", [error localizedDescription]];
|
||||
dmLogError([errorMessage UTF8String]);
|
||||
}
|
||||
|
||||
SiwaCredentialState state = STATE_UNKNOWN;
|
||||
switch(credentialState) {
|
||||
case ASAuthorizationAppleIDProviderCredentialAuthorized:
|
||||
dmLogInfo("credential state: ASAuthorizationAppleIDProviderCredentialAuthorized");
|
||||
state = STATE_AUTHORIZED;
|
||||
break;
|
||||
case ASAuthorizationAppleIDProviderCredentialRevoked:
|
||||
dmLogInfo("credential state: ASAuthorizationAppleIDProviderCredentialRevoked");
|
||||
state = STATE_REVOKED;
|
||||
break;
|
||||
case ASAuthorizationAppleIDProviderCredentialNotFound:
|
||||
dmLogInfo("credential state: ASAuthorizationAppleIDProviderCredentialNotFound");
|
||||
state = STATE_NOT_FOUND;
|
||||
break;
|
||||
default:
|
||||
dmLogInfo("credential state: unknown!!!");
|
||||
break;
|
||||
}
|
||||
|
||||
Siwa_QueueCredentialCallback(userId, state);
|
||||
}];
|
||||
}
|
||||
|
||||
// triggers the sign in with Apple native ui flow to begin.
|
||||
- (void) loginWithUI
|
||||
{
|
||||
ASAuthorizationAppleIDRequest* request = [self.m_idProvider createRequest];
|
||||
request.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail];
|
||||
|
||||
ASAuthorizationController* authController = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]];
|
||||
authController.presentationContextProvider = self;
|
||||
authController.delegate = self;
|
||||
|
||||
[authController performRequests];
|
||||
}
|
||||
|
||||
// the Auth controller needs to specify where to display the native login.
|
||||
// this is the function our SiwaManager delegate has to implement to provide that information.
|
||||
- (ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller {
|
||||
UIWindow *window = [UIApplication sharedApplication].keyWindow;
|
||||
return window;
|
||||
}
|
||||
|
||||
// the Auth controller callback for getting a response back from apple for a sign in
|
||||
- (void)authorizationController:(ASAuthorizationController *)controller
|
||||
didCompleteWithAuthorization:(ASAuthorization *)authorization {
|
||||
if ([authorization.credential class] == [ASAuthorizationAppleIDCredential class]) {
|
||||
ASAuthorizationAppleIDCredential* appleIdCredential = ((ASAuthorizationAppleIDCredential*) authorization.credential);
|
||||
|
||||
const char* appleUserId = [appleIdCredential.user UTF8String];
|
||||
const char* email = [appleIdCredential.email UTF8String];
|
||||
const char* givenName = [appleIdCredential.fullName.givenName UTF8String];
|
||||
const char* familyName = [appleIdCredential.fullName.familyName UTF8String];
|
||||
SiwaUserDetectionStatus userDetectionStatus = STATUS_UNSUPPORTED;
|
||||
if (appleIdCredential.realUserStatus == ASUserDetectionStatusLikelyReal)
|
||||
{
|
||||
userDetectionStatus = STATUS_LIKELY_REAL;
|
||||
}
|
||||
else if (appleIdCredential.realUserStatus == ASUserDetectionStatusUnknown)
|
||||
{
|
||||
userDetectionStatus = STATUS_UNKNOWN;
|
||||
}
|
||||
|
||||
appleIdCredential.realUserStatus;
|
||||
NSString* tokenString = [[NSString alloc] initWithData:appleIdCredential.identityToken encoding:NSUTF8StringEncoding];
|
||||
const char* identityToken = [tokenString UTF8String];
|
||||
|
||||
Siwa_QueueAuthSuccessCallback(identityToken, appleUserId, email, givenName, familyName, userDetectionStatus);
|
||||
}
|
||||
else
|
||||
{
|
||||
Siwa_QueueAuthFailureCallback("authorization failed!");
|
||||
}
|
||||
}
|
||||
|
||||
// The Auth controller callback for getting an error during authorization
|
||||
- (void)authorizationController:(ASAuthorizationController *)controller
|
||||
didCompleteWithError:(NSError *)error {
|
||||
NSString *errorMessage = [NSString stringWithFormat: @"Authorization error: %@", [error localizedDescription]];
|
||||
Siwa_QueueAuthFailureCallback([errorMessage UTF8String]);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
API_AVAILABLE(ios(13.0))
|
||||
static SiwaManager* g_SiwaManager = nil;
|
||||
|
||||
API_AVAILABLE(ios(13.0))
|
||||
SiwaManager* GetSiwaManager()
|
||||
{
|
||||
if(g_SiwaManager == nil)
|
||||
{
|
||||
g_SiwaManager = [[SiwaManager alloc] init];
|
||||
}
|
||||
|
||||
return g_SiwaManager;
|
||||
}
|
||||
|
||||
API_AVAILABLE(ios(13.0))
|
||||
// Kicks off the request to get the credential state of a provided user id.
|
||||
void Siwa_PlatformDoGetCredentialState() {
|
||||
SiwaManager *siwaMan = GetSiwaManager();
|
||||
[siwaMan getCredentialState];
|
||||
return;
|
||||
}
|
||||
|
||||
API_AVAILABLE(ios(13.0))
|
||||
// Kicks off the sign in with apple flow.
|
||||
void Siwa_PlatformDoAuthenticateWithApple() {
|
||||
SiwaManager *siwaMan = GetSiwaManager();
|
||||
[siwaMan loginWithUI];
|
||||
}
|
||||
|
||||
// Checks if Siwa is supported on this device by seeing if the main
|
||||
// class involved in all the siwa requests we use exists.
|
||||
bool Siwa_PlatformIsSupported()
|
||||
{
|
||||
return ([ASAuthorizationAppleIDProvider class] != nil);
|
||||
}
|
||||
|
||||
void Siwa_PlatformGetCredentialState() {
|
||||
Siwa_PlatformDoGetCredentialState();
|
||||
}
|
||||
|
||||
void Siwa_PlatformAuthenticateWithApple() {
|
||||
Siwa_PlatformDoAuthenticateWithApple();
|
||||
}
|
||||
|
||||
#endif
|
6
siwa/src/siwa_null.cpp
Executable file
6
siwa/src/siwa_null.cpp
Executable file
@@ -0,0 +1,6 @@
|
||||
#if !defined(DM_PLATFORM_IOS)
|
||||
extern "C" void siwa()
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
Reference in New Issue
Block a user