diff --git a/app.json b/app.json
index d98ae4b..68e9a3c 100644
--- a/app.json
+++ b/app.json
@@ -33,7 +33,10 @@
},
"permissions": [
"android.permission.ACCESS_COARSE_LOCATION",
- "android.permission.ACCESS_FINE_LOCATION"
+ "android.permission.ACCESS_FINE_LOCATION",
+ "android.permission.RECEIVE_BOOT_COMPLETED",
+ "android.permission.VIBRATE",
+ "android.permission.INTERNET"
],
"package": "com.gbrown.techtracker"
},
diff --git a/components/auth/AppleSignIn.native.tsx b/components/auth/AppleSignIniOS.tsx
similarity index 80%
rename from components/auth/AppleSignIn.native.tsx
rename to components/auth/AppleSignIniOS.tsx
index ad22c7f..e74a059 100644
--- a/components/auth/AppleSignIn.native.tsx
+++ b/components/auth/AppleSignIniOS.tsx
@@ -24,6 +24,7 @@ const AppleSignInButton = () => {
//projectId,
//});
if (credential.identityToken) {
+ const email = credential.email;
const full_name = (
credential.fullName &&
credential.fullName.givenName &&
@@ -41,16 +42,26 @@ const AppleSignInButton = () => {
});
console.log(JSON.stringify({ error, user }, null, 2))
if (!error) {
- if (user) {
- const data: any = {
- full_name,
- };
+ if (user && session) {
+ const data: any = {};
+ if (email) data.email = email;
+ if (full_name) data.full_name = full_name;
const { error: updateError } = await supabase.auth.updateUser({
data,
});
if (updateError) {
console.error('Error updating user metadata:', updateError);
}
+ const { error: updateProfileError } =
+ await supabase.from('profiles').upsert({
+ id: session.user.id,
+ username: data?.email.split('@')[0],
+ full_name: data?.full_name,
+ updated_at: new Date(),
+ });
+ if (updateProfileError) {
+ console.error('Error updating profile:', updateProfileError);
+ }
}
}
} else {
@@ -67,10 +78,10 @@ const AppleSignInButton = () => {
}
}
- if (Platform.OS !== 'ios') return
;
+ if (Platform.OS !== 'ios') return ;
else return (
-
+
{
/>
+
);
};
diff --git a/components/auth/AzureSignIn.tsx b/components/auth/AzureSignIn.tsx
new file mode 100644
index 0000000..99bbcc2
--- /dev/null
+++ b/components/auth/AzureSignIn.tsx
@@ -0,0 +1,109 @@
+import React, { useState } from 'react';
+import * as WebBrowser from 'expo-web-browser';
+import { makeRedirectUri, useAuthRequest, useAutoDiscovery } from 'expo-auth-session';
+import { Platform, StyleSheet } from 'react-native';
+import { supabase } from '@/lib/supabase';
+import { ThemedView, ThemedTextButton } from '@/components/theme';
+
+// This is important - it completes the auth session when the browser redirects back to your app
+WebBrowser.maybeCompleteAuthSession();
+
+const AzureSignIn = () => {
+ const [loading, setLoading] = useState(false);
+
+ // Get environment variables
+ const tenantId = process.env.EXPO_PUBLIC_AZURE_TENANT_ID as string;
+ const clientId = process.env.EXPO_PUBLIC_AZURE_CLIENT_ID as string;
+
+ // Set up the discovery endpoint for Azure AD
+ const discovery = useAutoDiscovery(
+ `https://login.microsoftonline.com/${tenantId}/v2.0`
+ );
+
+ // Create a redirect URI that matches what you configured in Azure
+ // This should match the redirect URI you set in your Supabase dashboard
+ const redirectUri = makeRedirectUri({
+ scheme: Platform.OS === 'web' ? undefined : 'com.gbrown.techtracker',
+ path: Platform.OS === 'web' ? 'auth/callback' : undefined,
+ });
+
+ // Set up the auth request with the needed scopes
+ const [request, response, promptAsync] = useAuthRequest(
+ {
+ clientId,
+ scopes: ['openid', 'profile', 'email', 'offline_access'],
+ redirectUri,
+ responseType: 'code', // Important for Supabase
+ usePKCE: true, // Use PKCE for added security
+ },
+ discovery
+ );
+
+ const signInWithAzure = async () => {
+ try {
+ setLoading(true);
+
+ // For Expo Go and mobile apps, we need to use the Expo Auth Session flow
+ if (Platform.OS !== 'web') {
+ // Launch the browser for authentication
+ const result = await promptAsync();
+
+ if (result.type === 'success') {
+ // If we got an authorization code, use Supabase to exchange it for a session
+ const { code } = result.params;
+
+ const { data, error } = await supabase.auth.exchangeCodeForSession(code);
+
+ if (error) {
+ throw error;
+ }
+
+ console.log('Successfully signed in with Azure!', data.user);
+ } else if (result.type === 'error') {
+ throw new Error(result.error?.message || 'Authentication failed');
+ } else if (result.type === 'cancel') {
+ console.log('User cancelled the login flow');
+ }
+ } else {
+ // For web, we can use Supabase's built-in OAuth flow
+ const { data, error } = await supabase.auth.signInWithOAuth({
+ provider: 'azure',
+ options: {
+ scopes: 'email profile openid offline_access',
+ redirectTo: window.location.origin + '/auth/callback',
+ },
+ });
+
+ if (error) {
+ throw error;
+ }
+ }
+ } catch (error) {
+ console.error('Error signing in with Azure:', error);
+ alert(`Error signing in: ${error.message}`);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ return (
+
+
+
+ );
+};
+export default AzureSignIn;
+
+const styles = StyleSheet.create({
+ verticallySpaced: {
+ paddingTop: 4,
+ paddingBottom: 4,
+ alignItems: 'center',
+ marginTop: 20,
+ },
+});
diff --git a/package-lock.json b/package-lock.json
index 883f787..011572d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -19,6 +19,7 @@
"aes-js": "^3.1.2",
"expo": "~52.0.28",
"expo-apple-authentication": "~7.1.3",
+ "expo-auth-session": "~6.0.3",
"expo-blur": "~14.0.3",
"expo-constants": "~17.0.7",
"expo-dev-client": "~5.0.12",
@@ -7668,6 +7669,24 @@
"react-native": "*"
}
},
+ "node_modules/expo-auth-session": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/expo-auth-session/-/expo-auth-session-6.0.3.tgz",
+ "integrity": "sha512-s7LmmMPiiY1NXrlcXkc4+09Hlfw9X1CpaQOCDkwfQEodG1uCYGQi/WImTnDzw5YDkWI79uC8F1mB8EIerilkDA==",
+ "license": "MIT",
+ "dependencies": {
+ "expo-application": "~6.0.2",
+ "expo-constants": "~17.0.5",
+ "expo-crypto": "~14.0.2",
+ "expo-linking": "~7.0.5",
+ "expo-web-browser": "~14.0.2",
+ "invariant": "^2.2.4"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-native": "*"
+ }
+ },
"node_modules/expo-blur": {
"version": "14.0.3",
"resolved": "https://registry.npmjs.org/expo-blur/-/expo-blur-14.0.3.tgz",
@@ -7693,6 +7712,18 @@
"react-native": "*"
}
},
+ "node_modules/expo-crypto": {
+ "version": "14.0.2",
+ "resolved": "https://registry.npmjs.org/expo-crypto/-/expo-crypto-14.0.2.tgz",
+ "integrity": "sha512-WRc9PBpJraJN29VD5Ef7nCecxJmZNyRKcGkNiDQC1nhY5agppzwhqh7zEzNFarE/GqDgSiaDHS8yd5EgFhP9AQ==",
+ "license": "MIT",
+ "dependencies": {
+ "base64-js": "^1.3.0"
+ },
+ "peerDependencies": {
+ "expo": "*"
+ }
+ },
"node_modules/expo-dev-client": {
"version": "5.0.12",
"resolved": "https://registry.npmjs.org/expo-dev-client/-/expo-dev-client-5.0.12.tgz",
diff --git a/package.json b/package.json
index aedb769..17fbdaa 100644
--- a/package.json
+++ b/package.json
@@ -56,7 +56,8 @@
"@expo/ngrok": "4.1.0",
"expo-notifications": "~0.29.13",
"expo-device": "~7.0.2",
- "expo-location": "~18.0.7"
+ "expo-location": "~18.0.7",
+ "expo-auth-session": "~6.0.3"
},
"devDependencies": {
"@babel/core": "^7.25.2",
diff --git a/services/PushNotificationManager.tsx b/services/PushNotificationManager.tsx
index 8b63869..c673189 100644
--- a/services/PushNotificationManager.tsx
+++ b/services/PushNotificationManager.tsx
@@ -72,6 +72,7 @@ async function registerForPushNotificationsAsync() {
}
const projectId = Constants.expoConfig?.extra?.eas?.projectId;
if (!projectId) {
+ console.warn('No project id found');
alert('Project ID not found');
return;
}