1660498200
Built using React JS, Redux, Firebase & Styled-Components within 2 days.
NOTE: PLEASE LET ME KNOW IF YOU DISCOVERED ANY BUG OR YOU HAVE ANY SUGGESTIONS
Author: AKASI1
Source code: https://github.com/AKASI1/Linkedin-Clone
#react-native #javascript #firebase #redux
1660444740
Youtube Clone (React + Redux + Firebase)
Getting Started with Create React App
This project was bootstrapped with Create React App.
In the project directory, you can run:
npm start
Runs the app in the development mode.
Open http://localhost:3000 to view it in your browser.
The page will reload when you make changes.
You may also see any lint errors in the console.
npm test
Launches the test runner in the interactive watch mode.
See the section about running tests for more information.
npm run build
Builds the app for production to the build
folder.
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.
Your app is ready to be deployed!
See the section about deployment for more information.
npm run eject
Note: this is a one-way operation. Once you eject
, you can't go back!
If you aren't satisfied with the build tool and configuration choices, you can eject
at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except eject
will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
You don't have to ever use eject
. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
You can learn more in the Create React App documentation.
To learn React, check out the React documentation.
This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting
This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size
This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration
This section has moved here: https://facebook.github.io/create-react-app/docs/deployment
npm run build
fails to minifyThis section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify
Author: Ashuu11
Source code: https://github.com/Ashuu11/Youtube_Clone_Ashu
License: MIT license
1660417020
- ReactJs Typescript
- TailwindCss
- Framer Motion
- Firebase
- Git
- Nodejs version 14 or higher (we recommend using nvm)
- yarn ( or npm )
- Open terminal and clone the repo :
git clone https://github.com/IslemMedjahdi/whatsapp-v2-clone/
- then :
yarn install
- then :
create a .env file in the root folder then put your firebase configuration ( check firebase documentation to get started )
REACT_APP_FIREBASE_API_KEY =
REACT_APP_FIREBASE_AUTH_DOMAIN =
REACT_APP_FIREBASE_PROJECT_ID =
REACT_APP_FIREBASE_STORAGE_BUCKET =
REACT_APP_FIREBASE_MESSAGING_SENDER_ID =
REACT_APP_FIREBASE_APP_ID =
- then :
yarn start
Author: IslemMedjahdi
Source code: https://github.com/IslemMedjahdi/whatsapp-v2-clone
#react #typescript #javascript #firebase #tailwindcss
1660402000
Step 1: Before you can add Firebase to your app, you need to create a Firebase project to connect to your application. Visit Understand Firebase Projects
to learn more about Firebase projects.
Step 2: To use Firebase in your app, you need to register your app with your Firebase project. Registering your app is often called "adding" your app to your project.
Also, register a web app if using on the web. Follow on the screen instructions to initialize the project.
Add the latest version 'firebase-messaging' CDN from here in index.html. (Tested on version 8.6.1)
Step 3: Add a Firebase configuration file and the SDK's. (google-services)
Step 4: Lastly, add firebase_core
as a dependency in your pubspec.yaml file. and call Firebase.initializeApp()
in the main
method as shown:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(_MainApp());
}
Add the default channel in AndroidManifest in the <application>
tag. Pass the same in the channelId parameter in the FirebaseNotificationsHandler
widget to enable custom sounds.
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="Notifications" />
The android:value
should be the same as the channel id in FirebaseNotificationsHandler. The default value for channel id is "Notifications".
Also, add this intent-filter in AndroidManifest in the <activity>
tag with android:name=".MainActivity"
<intent-filter>
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
Provide the vapidKey in FirebaseNotificationsHandler from the cloud messaging settings by generating a new Web push certificate
Add this script tag in index.html after adding the firebase config script
<script>
if ("serviceWorker" in navigator) {
window.addEventListener("load", function () {
// navigator.serviceWorker.register("/flutter_service_worker.js");
navigator.serviceWorker.register("/firebase-messaging-sw.js");
});
}
</script>
Now, finally create a file firebase-messaging-sw.js
in the web
folder itself and paste the following contents. Add your own firebase app config here.
importScripts("https://www.gstatic.com/firebasejs/7.15.5/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/7.15.5/firebase-messaging.js");
firebase.initializeApp(
// YOUR FIREBASE CONFIG MAP HERE
);
const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(function (payload) {
const promiseChain = clients
.matchAll({
type: "window",
includeUncontrolled: true
})
.then(windowClients => {
for (let i = 0; i < windowClients.length; i++) {
const windowClient = windowClients[i];
windowClient.postMessage(payload);
}
})
.then(() => {
return registration.showNotification("New Message");
});
return promiseChain;
});
self.addEventListener('notificationclick', function (event) {
console.log('notification received: ', event)
});
To use this plugin, add firebase_notifications_handler
as a dependency in your pubspec.yaml file.
dependencies:
flutter:
sdk: flutter
firebase_notifications_handler:
First and foremost, import the widget.
import 'package:firebase_notifications_handler/firebase_notifications_handler.dart';
Wrap the FirebaseNotificationsHandler
on a widget to enable your application to receive notifications. Typically wrap it on the screen, when you have all the initial setup done. (like on the home screen).
When the app launches, the splash screen typically loads all the stuff, initializes the users and sends to the home screen, then the onTap will trigger, and can be handled accordingly from the callback.
If wrapped on the material app, then you might push the user to the specified screen too early, before initializing the user or something that you need.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return FirebaseNotificationsHandler(
child: HomeScreen(),
);
}
}
Although, the widget automatically initializes the fcmToken, but if the FCM token is needed before the widget is built, then use the initializeFCMToken() function to initialize the token. Which will return the initialized token.
Also, keep in mind, when the widget is built, the onFCMTokenInitialize callback will also fire, with the same token.
There are multiple parameters that can be passed to the widget, some of them are shown.
FirebaseNotificationsHandler(
onFCMTokenInitialize: (_, token) => fcmToken = token,
onFCMTokenUpdate: (_, token) {
fcmToken = token;
// await User.updateFCM(token);
},
onTap: (navigatorState, appState, payload) {
print("Notification tapped with $appState & payload $payload");
final context = navigatorState.currentContext!;
navigatorState.currentState!.pushNamed('newRouteName');
// OR
Navigator.pushNamed(context, 'newRouteName');
},
channelId: 'ChannelId',
enableLogs: true,
// ... and a lot more
),
You can check the remaining parameters here. They are fully documented and won't face an issue while using them
You can use the in-built sendNotification
static method on the FirebaseNotificationsHandler
widget to trigger the notification.
await FirebaseNotificationsHandler.sendNotification(
cloudMessagingServerKey: '<YOUR_CLOUD_MESSAGING_SERVER_KEY>',
title: 'This is a test notification',
body: 'This describes this notification',
fcmTokens: [
'fcmDeviceToken1',
'fcmDeviceToken2',
],
payload: {
'key': 'value',
},
);
OR
To send FCM notification using REST API:
Make a POST
request @https://fcm.googleapis.com/fcm/send
Also, add 2 headers:
Content-Type: application/json
Authorization: key=<SERVER_KEY_FROM_FIREBASE_CLOUD_MESSAGING>
You can find the server key from the cloud messaging settings in the firebase console.
The body is framed as follows:
{
"to": "<FCM_TOKEN_HERE>",
"registration_ids": [],
"notification": {
"title": "Title here",
"body": "Body here",
"image": "Image url here"
},
"data": {
"click_action":"FLUTTER_NOTIFICATION_CLICK"
}
}
You can pass all the fcm tokens in the "registration_ids" list if there are multiple users or only pass one fcm token in the "to" parameter for single user.
Add all the rest of the payload data in "data" field which will be provided in the onTap
callback.
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_notifications_handler/firebase_notifications_handler.dart';
import 'package:flutter/material.dart';
import 'package:notifications_handler_demo/firebase_options.dart';
import 'package:notifications_handler_demo/screens/splash_screen.dart';
import 'package:notifications_handler_demo/utils/app_theme.dart';
import 'package:notifications_handler_demo/utils/globals.dart';
import 'package:notifications_handler_demo/utils/helpers.dart';
import 'package:notifications_handler_demo/utils/route_generator.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
runApp(const _MainApp());
}
class _MainApp extends StatelessWidget {
static const id = '_MainApp';
const _MainApp({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return FirebaseNotificationsHandler(
defaultNavigatorKey: Globals.navigatorKey,
onOpenNotificationArrive: (_, payload) {
log(
id,
msg: "Notification received while app is open with payload $payload",
);
},
onTap: (navigatorState, appState, payload) {
showSnackBar('appState: $appState\npayload: $payload');
log(
id,
msg: "Notification tapped with $appState & payload $payload",
);
},
onFCMTokenInitialize: (_, token) => Globals.fcmToken = token,
onFCMTokenUpdate: (_, token) => Globals.fcmToken = token,
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'FirebaseNotificationsHandler Demo',
navigatorKey: Globals.navigatorKey,
scaffoldMessengerKey: Globals.scaffoldMessengerKey,
theme: AppTheme.lightTheme,
darkTheme: AppTheme.darkTheme,
onGenerateRoute: RouteGenerator.generateRoute,
initialRoute: SplashScreen.id,
),
);
}
}
See the example
directory for a complete sample app.
Rithik Bhandari
Run this command:
With Flutter:
$ flutter pub add firebase_notifications_handler
This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get
):
dependencies:
firebase_notifications_handler: ^1.0.9
Alternatively, your editor might support flutter pub get
. Check the docs for your editor to learn more.
Now in your Dart code, you can use:
import 'package:firebase_notifications_handler/firebase_notifications_handler.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_notifications_handler/firebase_notifications_handler.dart';
import 'package:flutter/material.dart';
import 'package:notifications_handler_demo/firebase_options.dart';
import 'package:notifications_handler_demo/screens/splash_screen.dart';
import 'package:notifications_handler_demo/utils/app_theme.dart';
import 'package:notifications_handler_demo/utils/globals.dart';
import 'package:notifications_handler_demo/utils/helpers.dart';
import 'package:notifications_handler_demo/utils/route_generator.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
runApp(const _MainApp());
}
class _MainApp extends StatelessWidget {
static const id = '_MainApp';
const _MainApp({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return FirebaseNotificationsHandler(
defaultNavigatorKey: Globals.navigatorKey,
onOpenNotificationArrive: (_, payload) {
log(
id,
msg: "Notification received while app is open with payload $payload",
);
},
onTap: (navigatorState, appState, payload) {
showSnackBar('appState: $appState\npayload: $payload');
log(
id,
msg: "Notification tapped with $appState & payload $payload",
);
},
onFCMTokenInitialize: (_, token) => Globals.fcmToken = token,
onFCMTokenUpdate: (_, token) => Globals.fcmToken = token,
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'FirebaseNotificationsHandler Demo',
navigatorKey: Globals.navigatorKey,
scaffoldMessengerKey: Globals.scaffoldMessengerKey,
theme: AppTheme.lightTheme,
darkTheme: AppTheme.darkTheme,
onGenerateRoute: RouteGenerator.generateRoute,
initialRoute: SplashScreen.id,
),
);
}
}
Download Details:
Author: rithik-dev
Source Code: https://github.com/rithik-dev/firebase_notifications_handler
1660397605
FirebasePhoneAuthHandler For Flutter
Step 1: Before you can add Firebase to your app, you need to create a Firebase project to connect to your application. Visit Understand Firebase Projects
to learn more about Firebase projects.
Step 2: To use Firebase in your app, you need to register your app with your Firebase project. Registering your app is often called "adding" your app to your project.
Also, register a web app if using on the web. Follow on the screen instructions to initialize the project.
Add the latest version 'firebase-auth' CDN from here. (Tested on version 8.6.1)
Step 3: Add a Firebase configuration file and the SDK's. (google-services)
Step 4: When the basic setup is done, open the console and then the project and head over to Authentication
from the left drawer menu.
Step 5: Click on Sign-in method
next to the Users
tab and enable Phone
.
Step 6: Follow the additional configuration steps for the platforms to avoid any errors.
Step 7: IMPORTANT: Do not forget to enable the Android Device Verification
service from Google Cloud Platform. (make sure the correct project is selected).
Step 8: Lastly, add firebase_core
as a dependency in your pubspec.yaml file. and call Firebase.initializeApp()
in the main
method as shown:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(_MainApp());
}
To use this plugin, add firebase_phone_auth_handler
as a dependency in your pubspec.yaml file.
dependencies:
flutter:
sdk: flutter
firebase_phone_auth_handler:
First and foremost, import the widget.
import 'package:firebase_phone_auth_handler/firebase_phone_auth_handler.dart';
Wrap the MaterialApp
with FirebasePhoneAuthProvider
to enable your application to support phone authentication like shown.
class _MainApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return FirebasePhoneAuthProvider(
child: MaterialApp(
debugShowCheckedModeBanner: false,
home: HomeScreen(),
),
);
}
}
You can now add a FirebasePhoneAuthHandler
widget to your widget tree and pass all the required parameters to get started.
FirebasePhoneAuthHandler(
phoneNumber: "+919876543210",
builder: (context, controller) {
return SizedBox.shrink();
},
),
The phone number is the number to which the OTP will be sent which should be formatted in the following way:
+919876543210 - where +91 is the country code and 9876543210 is the phone number.
The widget returned from the builder
is rendered on the screen. The builder exposes a controller
which contains various variables and methods.
Callbacks such as onLoginSuccess
or onLoginFailed
can be passed to the widget.
onLoginSuccess
is called whenever the otp was sent to the mobile successfully and was either auto verified or verified manually by calling verifyOTP
function in the controller. The callback exposes UserCredential
object which can be used to find user UID and other stuff. The boolean provided is whether the OTP was auto verified or verified manually be calling verifyOTP
. True if auto verified and false is verified manually.
onLoginFailed
is called if an error occurs while sending OTP or verifying the OTP or any internal error occurs, callback is triggered exposing FirebaseAuthException
which can be used to handle the error.
onCodeSent
is called when the OTP is successfully sent to the phone number.
FirebasePhoneAuthHandler(
phoneNumber: "+919876543210",
// If true, the user is signed out before the onLoginSuccess callback is fired when the OTP is verified successfully.
signOutOnSuccessfulVerification: false,
linkWithExistingUser: false,
builder: (context, controller) {
return SizedBox.shrink();
},
onLoginSuccess: (userCredential, autoVerified) {
debugPrint("autoVerified: $autoVerified");
debugPrint("Login success UID: ${userCredential.user?.uid}");
},
onLoginFailed: (authException, stackTrace) {
debugPrint("An error occurred: ${authException.message}");
},
onError: (error, stackTrace) {},
),
To logout the current user(if any), simply call
await FirebasePhoneAuthHandler.signOut(context);
controller.signOut()
can also be used to logout the current user if the functionality is needed in the same screen as the widget itself (where controller
is the variable passed in the callback from the builder method in the widget).
By default, the reCAPTCHA widget is a fully managed flow which provides security to your web application. The widget will render as an invisible widget when the sign-in flow is triggered. An "invisible" widget will appear as a full-page modal on-top of your application like demonstrated below.
Although, a RecaptchaVerifier
instance can be passed which can be used to manage the widget.
Use the function recaptchaVerifierForWebProvider
in FirebasePhoneAuthHandler
which gives a boolean to check whether the current platform is Web or not.
NOTE
: Do not pass a RecaptchaVerifier
instance if the platform is not web, else an error occurs.
Example:
recaptchaVerifierForWebProvider: (isWeb) {
if (isWeb) return RecaptchaVerifier();
},
It is however possible to display an inline widget which the user has to explicitly press to verify themselves.
To add an inline widget, specify a DOM element ID to the container argument of the RecaptchaVerifier
instance. The element must exist and be empty otherwise an error will be thrown. If no container argument is provided, the widget will be rendered as "invisible".
RecaptchaVerifier(
container: 'recaptcha',
size: RecaptchaVerifierSize.compact,
theme: RecaptchaVerifierTheme.dark,
onSuccess: () => print('reCAPTCHA Completed!'),
onError: (FirebaseAuthException error) => print(error),
onExpired: () => print('reCAPTCHA Expired!'),
),
If the reCAPTCHA badge does not disappear automatically after authentication is done, try adding the following code in onLoginSuccess
so that it disappears when the login process is done.
Firstly import querySelector
from dart:html
.
import 'dart:html' show querySelector;
Then add this in onLoginSuccess
callback.
final captcha = querySelector('#__ff-recaptcha-container');
if (captcha != null) captcha.hidden = true;
If you want to completely disable the reCAPTCHA badge (typically appears on the bottom right), add this CSS style in the web/index.html
outside any other tag.
<style>
.grecaptcha-badge { visibility: hidden; }
</style>
I usually have a phone number input field, which handles phone number input. Then pass the phone number to the VerifyPhoneNumberScreen
widget from the example app.
// probably some ui or dialog to get the phone number
final phoneNumber = _getPhoneNumber();
// then call
void _verifyPhoneNumber() async {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => VerifyPhoneNumberScreen(phoneNumber: phoneNumber),
),
);
}
/// route to home screen or somewhere in the onLoginSuccess callback for [VerifyPhoneNumberScreen]
import 'package:firebase_phone_auth_handler/firebase_phone_auth_handler.dart';
import 'package:flutter/material.dart';
import 'package:phone_auth_handler_demo/screens/home_screen.dart';
import 'package:phone_auth_handler_demo/utils/helpers.dart';
import 'package:phone_auth_handler_demo/widgets/custom_loader.dart';
import 'package:phone_auth_handler_demo/widgets/pin_input_field.dart';
class VerifyPhoneNumberScreen extends StatefulWidget {
static const id = 'VerifyPhoneNumberScreen';
final String phoneNumber;
const VerifyPhoneNumberScreen({
Key? key,
required this.phoneNumber,
}) : super(key: key);
@override
State<VerifyPhoneNumberScreen> createState() =>
_VerifyPhoneNumberScreenState();
}
class _VerifyPhoneNumberScreenState extends State<VerifyPhoneNumberScreen>
with WidgetsBindingObserver {
bool isKeyboardVisible = false;
late final ScrollController scrollController;
@override
void initState() {
scrollController = ScrollController();
WidgetsBinding.instance.addObserver(this);
super.initState();
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
scrollController.dispose();
super.dispose();
}
@override
void didChangeMetrics() {
final bottomViewInsets = WidgetsBinding.instance.window.viewInsets.bottom;
isKeyboardVisible = bottomViewInsets > 0;
}
// scroll to bottom of screen, when pin input field is in focus.
Future<void> _scrollToBottomOnKeyboardOpen() async {
while (!isKeyboardVisible) {
await Future.delayed(const Duration(milliseconds: 50));
}
await Future.delayed(const Duration(milliseconds: 250));
await scrollController.animateTo(
scrollController.position.maxScrollExtent,
duration: const Duration(milliseconds: 250),
curve: Curves.easeIn,
);
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: FirebasePhoneAuthHandler(
phoneNumber: widget.phoneNumber,
signOutOnSuccessfulVerification: false,
linkWithExistingUser: false,
autoRetrievalTimeOutDuration: const Duration(seconds: 60),
otpExpirationDuration: const Duration(seconds: 60),
onCodeSent: () {
log(VerifyPhoneNumberScreen.id, msg: 'OTP sent!');
},
onLoginSuccess: (userCredential, autoVerified) async {
log(
VerifyPhoneNumberScreen.id,
msg: autoVerified
? 'OTP was fetched automatically!'
: 'OTP was verified manually!',
);
showSnackBar('Phone number verified successfully!');
log(
VerifyPhoneNumberScreen.id,
msg: 'Login Success UID: ${userCredential.user?.uid}',
);
Navigator.pushNamedAndRemoveUntil(
context,
HomeScreen.id,
(route) => false,
);
},
onLoginFailed: (authException, stackTrace) {
log(
VerifyPhoneNumberScreen.id,
msg: authException.message,
error: authException,
stackTrace: stackTrace,
);
switch (authException.code) {
case 'invalid-phone-number':
// invalid phone number
return showSnackBar('Invalid phone number!');
case 'invalid-verification-code':
// invalid otp entered
return showSnackBar('The entered OTP is invalid!');
// handle other error codes
default:
showSnackBar('Something went wrong!');
// handle error further if needed
}
},
onError: (error, stackTrace) {
log(
VerifyPhoneNumberScreen.id,
error: error,
stackTrace: stackTrace,
);
showSnackBar('An error occurred!');
},
builder: (context, controller) {
return Scaffold(
appBar: AppBar(
leadingWidth: 0,
leading: const SizedBox.shrink(),
title: const Text('Verify Phone Number'),
actions: [
if (controller.codeSent)
TextButton(
onPressed: controller.isOtpExpired
? () async {
log(VerifyPhoneNumberScreen.id, msg: 'Resend OTP');
await controller.sendOTP();
}
: null,
child: Text(
controller.isOtpExpired
? 'Resend'
: '${controller.otpExpirationTimeLeft.inSeconds}s',
style: const TextStyle(color: Colors.blue, fontSize: 18),
),
),
const SizedBox(width: 5),
],
),
body: controller.isSendingCode
? Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: const [
CustomLoader(),
SizedBox(height: 50),
Center(
child: Text(
'Sending OTP',
style: TextStyle(fontSize: 25),
),
),
],
)
: ListView(
padding: const EdgeInsets.all(20),
controller: scrollController,
children: [
Text(
"We've sent an SMS with a verification code to ${widget.phoneNumber}",
style: const TextStyle(fontSize: 25),
),
const SizedBox(height: 10),
const Divider(),
if (controller.isListeningForOtpAutoRetrieve)
Column(
children: const [
CustomLoader(),
SizedBox(height: 50),
Text(
'Listening for OTP',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.w600,
),
),
SizedBox(height: 15),
Divider(),
Text('OR', textAlign: TextAlign.center),
Divider(),
],
),
const SizedBox(height: 15),
const Text(
'Enter OTP',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 15),
PinInputField(
length: 6,
onFocusChange: (hasFocus) async {
if (hasFocus) await _scrollToBottomOnKeyboardOpen();
},
onSubmit: (enteredOtp) async {
final verified =
await controller.verifyOtp(enteredOtp);
if (verified) {
// number verify success
// will call onLoginSuccess handler
} else {
// phone verification failed
// will call onLoginFailed or onError callbacks with the error
}
},
),
],
),
);
},
),
);
}
}
See the example
directory for a complete sample app.
Rithik Bhandari
Run this command:
With Flutter:
$ flutter pub add firebase_phone_auth_handler
This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get
):
dependencies:
firebase_phone_auth_handler: ^1.0.6
Alternatively, your editor might support flutter pub get
. Check the docs for your editor to learn more.
Now in your Dart code, you can use:
import 'package:firebase_phone_auth_handler/firebase_phone_auth_handler.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_phone_auth_handler/firebase_phone_auth_handler.dart';
import 'package:flutter/material.dart';
import 'package:phone_auth_handler_demo/firebase_options.dart';
import 'package:phone_auth_handler_demo/screens/splash_screen.dart';
import 'package:phone_auth_handler_demo/utils/app_theme.dart';
import 'package:phone_auth_handler_demo/utils/globals.dart';
import 'package:phone_auth_handler_demo/utils/route_generator.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
runApp(const _MainApp());
}
class _MainApp extends StatelessWidget {
const _MainApp({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return FirebasePhoneAuthProvider(
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'FirebasePhoneAuthHandler Demo',
scaffoldMessengerKey: Globals.scaffoldMessengerKey,
theme: AppTheme.lightTheme,
darkTheme: AppTheme.darkTheme,
onGenerateRoute: RouteGenerator.generateRoute,
initialRoute: SplashScreen.id,
),
);
}
}
Download Details:
Author: rithik-dev
Source Code: https://github.com/rithik-dev/firebase_phone_auth_handler
1660373535
A simple react package ment to make React/NextJS firebase authentication easy.
currently supports email/password and Google authentication, more will be added soon
This file will house your Firebase config as well as auth object and its providers. Config object comes from Firebase console.
import { initializeApp } from "firebase/app";
import { getAuth, GoogleAuthProvider } from "firebase/auth";
const firebaseConfig = {
apiKey: "API-KEY",
authDomain: "EXAMPLE-DOMAIN.firebaseapp.com",
projectId: "PROJECT-ID",
storageBucket: "DOMAIN.appspot.com",
messagingSenderId: "ID",
appId: "ID",
measurementId: "ID",
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
// init auth
export const auth = getAuth(app);
// init google provider
export const gProvider = new GoogleAuthProvider();
gProvider.setCustomParameters({ prompt: "select_account" });
The provider takes in the auth object, the google provider, and the persistence type (https://firebase.google.com/docs/auth/web/auth-state-persistence).
import { auth, gProvider } from "./firebase_client";
import { browserLocalPersistence } from "firebase/auth";
ReactDOM.createRoot(document.getElementById("root")!).render(
<FBAuthProvider
fb_auth={auth}
g_provider={gProvider}
persistence_type={browserLocalPersistence}
>
<React.StrictMode>
<App />
</React.StrictMode>
</FBAuthProvider>
);
Basic App.tsx example:
import { useFBAuth } from "@matterhorn-studios/react-fb-auth";
function App() {
const { user, loading, error, googleSignIn, logOut } = useFBAuth();
if (loading) return <h1>LOADING</h1>;
if (error) return <h1>Error: {error.message}</h1>;
return (
<div>
{user ? (
<>
<div>{user.displayName}</div>
<button onClick={logOut}>log out</button>
</>
) : (
<>
<div>no user found</div>
<button onClick={googleSignIn}>google sign in</button>
</>
)}
</div>
);
}
export default App;
googleSignIn
Prompts the user to sign in with google, populates the user, loading, and error objectemailSignIn(email: string, password: string)
Signs the user in with the provided email and password, populates the user, loading, and error objectemailSignUp(email: string, password: string)
Signs the user up with the provided email and password, populates the user, loading, and error objectlogOut
Logs the user outclearError
Clears the error object (resets it to null)Author: Matterhorn-Studios
Source code: https://github.com/Matterhorn-Studios/ReactFBAuth
#react #typescript #NextJS #firebase
1660295040
Contact Me at bijay.work37@gmail.com as many people have used the guest account now so easier to find me by email deployed on vercel
Change firebase config file to connect your own firebase app
Run client:
cd client
npm install
npm start
Author: Bijayb37
Source code: https://github.com/Bijayb37/Firebase-chatrooms
1660235340
This is an open chat web app that I made using Google Firebase.
Hosting a server
To host your own chat server, first open the terminal and type in git clone https://github.com/EesaZahed/laser-chat.git
. Next, type cd laser-chat
and npm i
in the terminal.
Next, create a Google Firebase web project at https://console.firebase.google.com/, and enable a firestore database, and also add a method for user authentication with an the users Google Account. Once you create your project, go to your project settings, and copy the firebaseConfig
object, and paste it in src/firebase/config.js
.
To finally run it, type in the terminal of your project's directory npm start
.
Your chat server is online and anyone with your API keys in the firebaseConfig object can edit your database. For more information about Firebase security, please read more about this at https://firebase.google.com/docs/projects/api-keys.
For your database rules, use the following:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{id} {
allow read, create, update: if isUserAuthenticated();
}
match /messages/{id} {
allow read, create : if isUserAuthenticated();
}
function isUserAuthenticated() {
return request.auth.uid != null;
}
}
}
Author: EesaZahed
Source code: https://github.com/EesaZahed/laser-chat-2.0
1660189620
Todo List CRUD and OAuth with Firebase
Esta es una app hecha con React y Firebase en la que puedas crear, leer, actualizar y borrar tareas dentro de una lista de tareas. El usuario solo pude crear, leer, actualizar y borrar las tareas que le pertenecen. Para eso el usuario debe estar logueado con Google, Facebook o Github.
Clona el repositorio
git clone https://github.com/adonyssantos/cic-evaluation-app.git
Ve a la carpeta del proyecto
cd cic-evaluation-app
Instala las dependencias
npm install
Ejecuta la app
npm run start
El usuario debe estar logueado para poder crear, leer, actualizar y borrar tareas. Para eso se utiliza una autenticación con Firebase. Se utilizan 3 providers para el login: Google, Facebook y Github.
Dentro de la carpeta src/utils/firebase-auth.js
se encuentra toda la lógica de autenticación.
Funciones:
loginWithGoogle
loginWithFacebook
loginWithGithub
logout
Se almacenara en un state la información del usuario logueado. (email, photoUrl, uid...)
La base de datos utilizada es Firestore. Solo existe una colección llamada todos
. Aquí se va a guardar toda la información.
id
: Es el identificador de la tarea.title
: Es el título de la tarea.completed
: Es un booleano que indica si la tarea está completada o no.userRef
: Id del usuario que creó la tarea.Dentro de la carpeta src/utils/firebase-db.js
se encuentra toda la lógica de base de datos.
Funciones:
createTodo
readTodos
updateTodo
deleteTodo
Al momento de leer la colección, se va a filtrar utilizando el id del usuario que está logueado. Ejemplo: userRef == user.uid
.
La aplicación esta alojada en Firebase.
Comando para alojar la app:
firebase deploy
Author: adonyssantos
Source code: https://github.com/adonyssantos/todo-list-react-firebase
1660166940
This is a clone of Netflix website built using React.JS as a Front-end. It's not a replica, and it doesn't have all the features of Netflix website. it's a similar version of Netflix with my own design touch, showing my abilities in React.JS to build something advancedlike Netflix. It contains the home page, sign-in page, sign-up page, browse page.
Take a look at the live version here: https://netflix-clonee01.netlify.app/ :octocat: :heart_eyes:
Basically, this project was developed based on the following technologies:
Getting Started with Create React App
This project was bootstrapped with Create React App.
In the project directory, you can run:
npm start
Runs the app in the development mode.
Open http://localhost:3000 to view it in your browser.
The page will reload when you make changes.
You may also see any lint errors in the console.
npm test
Launches the test runner in the interactive watch mode.
See the section about running tests for more information.
npm run build
Builds the app for production to the build
folder.
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.
Your app is ready to be deployed!
See the section about deployment for more information.
npm run eject
Note: this is a one-way operation. Once you eject
, you can't go back!
If you aren't satisfied with the build tool and configuration choices, you can eject
at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except eject
will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
You don't have to ever use eject
. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
You can learn more in the Create React App documentation.
To learn React, check out the React documentation.
This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting
This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size
This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration
This section has moved here: https://facebook.github.io/create-react-app/docs/deployment
npm run build
fails to minifyThis section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify
Author: MuradRahmanzada
Source code: https://github.com/MuradRahmanzada/Netflix-clone
1660138740
This application uses the following open-source packages:
Core ones.
Stylization.
Others.
Code formatter, and other environment development tools.
made by niloodev | Ezequiel Nilo
ANY TIPS OR FEEDBACK IS HIGHLY APPRECIATED! 🐸
Author: niloodev
Source code: https://github.com/niloodev/fullstack-task-app
1660079880
Instagram 2.0 Clone With ReactJs!
This project was bootstrapped with Create React App.
npx create-next-app instagram_clone
cd instagram_clone
Install tailwindcss and its peer dependencies via npm, and then run the init command to generate both tailwind.config.js and postcss.config.js.
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
Add the paths to all of your template files in your tailwind.config.js file.
module.exports = {
content: [
"./pages/**/*.{js,ts,jsx,tsx}",
"./components/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
Add the @tailwind directives for each of Tailwind’s layers to your ./styles/globals.css file.
@tailwind base;
@tailwind components;
@tailwind utilities;
This is a Next.js project bootstrapped with create-next-app
.
First, run the development server:
npm run dev
# or
yarn dev
Open http://localhost:3000 with your browser to see the result.
You can start editing the page by modifying pages/index.js
. The page auto-updates as you edit the file.
API routes can be accessed on http://localhost:3000/api/hello. This endpoint can be edited in pages/api/hello.js
.
The pages/api
directory is mapped to /api/*
. Files in this directory are treated as API routes instead of React pages.
To learn more about Next.js, take a look at the following resources:
You can check out the Next.js GitHub repository - your feedback and contributions are welcome!
The easiest way to deploy your Next.js app is to use the Vercel Platform from the creators of Next.js.
Check out our Next.js deployment documentation for more details.
npm install @heroicons/react
npm install --save-dev @faker-js/faker
npm i tailwind-scrollbar
npm i tailwind-scrollbar-hide
npm i @tailwindcss/forms
npm install recoil
npm install @headlessui/react
npm i react-moment
Author: SashenJayathilaka
Source code: https://github.com/SashenJayathilaka/Instagram-Clone
#next #nextjs #react #javscript #nextauth #firebase #tailwindcss
1659975660
Firebase est une plate-forme cloud passionnante de Google disponible pour les entreprises aujourd'hui. Firebase connecte tout, des simples sites Web statiques aux appareils IoT en passant par l'IA et les plates-formes d'apprentissage automatique. La plateforme fournit divers services pour faciliter ces connexions, comme le stockage et l'authentification.
Dans ce didacticiel, vous découvrirez deux produits Firebase principaux : Cloud Functions for Firebase et Firebase Hosting. L'hébergement sert à déployer des applications Web statiques. Les fonctions sont la plate-forme sans serveur Firebase. Vous allez créer une application statique à l'aide de React qui authentifie les utilisateurs via la bibliothèque React d'Okta. Après avoir obtenu un jeton d'accès du serveur d'autorisation d'Okta, vous utiliserez une fonction Firebase pour échanger le jeton Okta contre un jeton Firebase et connecter l'utilisateur à l'aide de la structure d'authentification de Firebase. Vous obtiendrez des informations utilisateur supplémentaires en appelant le userInfo
point de terminaison sur votre serveur d'autorisation Okta et en incluant ces données dans votre jeton Firebase. Enfin, vous allez créer un autre point de terminaison de fonction pour gérer une requête HTTP simple nécessitant un utilisateur authentifié.
Une fois que vous avez créé votre application, vous la déploierez sur la plate-forme Firebase pour une utilisation publique à l'aide de la CLI Firebase.
Avant de commencer, vous aurez besoin d'un compte développeur Okta gratuit. Installez l' interface de ligne de commande Okta et exécutez- okta register
la pour vous inscrire à un nouveau compte. Si vous avez déjà un compte, exécutez okta login
. Ensuite, courez okta apps create
. Sélectionnez le nom de l'application par défaut ou modifiez-le comme bon vous semble. Choisissez Application monopage et appuyez sur Entrée .
Utilisez http://localhost:3000/login/callback
pour l'URI de redirection et acceptez l'URI de redirection de déconnexion par défaut de http://localhost:3000/login
.
Ensuite, ouvrez la console Firebase et cliquez sur Ajouter un projet . Donnez un nom à votre projet, de préférence okta-firebase
. Pour l'instant, vous pouvez désactiver les analyses et créer le projet. Une fois cette opération terminée, vous pourrez accéder au tableau de bord du projet.
Tout d'abord, cliquez sur le bouton Mettre à niveau à côté de l' option Spark en bas de votre écran. Changez votre plan en Blaze et si vous le souhaitez, définissez un budget de facturation de 1 $ pour vous informer lorsque vous encourez des frais. Blaze est payant et les tarifs sont assez généreux pour les projets de loisirs. Vous ne devriez pas encourir de frais pour le moment, mais le budget vous indiquera si vous le faites.
Cliquez sur la roue des paramètres à côté de Vue d'ensemble du projet et cliquez sur Paramètres du projet . Au bas de la page de présentation, une invite vous invite à sélectionner une plate-forme pour commencer et à sélectionner une application Web (elle ressemblera à </> ). Donnez le surnom à votre application okta-firebase-demo
et sélectionnez Configurer également l'hébergement Firebase pour cette application . Cliquez sur Enregistrer l'application et dans un instant, vous verrez du code JavaScript pour configurer votre application Firebase.
Conservez ces informations car vous en aurez besoin dans votre application. Cliquez sur le reste de l'assistant et revenez à votre console. Accédez à nouveau à la section Paramètres du projet et accédez à l' onglet Comptes de service . Cliquez sur Générer une nouvelle clé privée et laissez ce fichier se télécharger. Vous en aurez besoin dans votre fonction Firebase sous peu.
Enfin, cliquez sur Build > Authentication dans la navigation latérale et cliquez sur Get Started . Le fait d' appuyer sur le bouton Démarrer génère une clé d'API Web requise pour utiliser les fonctions d'authentification.
Ensuite, créez votre application React.
npx create-react-app@5 okta-firebase
cd okta-firebase
La commande npx échafaudera une nouvelle application React version 18 pour vous.
Ensuite, vous devrez installer quelques dépendances pour vous aider.
npm i @okta/okta-react@6.4.3
npm i @okta/okta-auth-js@6.2.0
npm i react-router-dom@5.3.0
npm i bootstrap@5.1.3
npm i firebase@9.8.1
Tout d'abord, vous souhaitez installer le @okta/okta-react
package pour aider à authentifier les utilisateurs et à obtenir les jetons du serveur d'autorisation Okta. Ce package vous aidera à accéder à l'état d'authentification, à diriger les utilisateurs vers la page de connexion Okta et à gérer les rappels.
@okta/okta-react
repose sur le @okta/okta-auth-js
package, vous devez donc l'installer.
Ensuite, vous voulez installer react-router-dom
. Ce package configurera la route de rappel pour vous et toute autre route dont vous pourriez avoir besoin.
Enfin, vous utiliserez le firebase
package pour appeler les différentes fonctionnalités de la plate-forme dans Firebase, telles que les fonctions et l'authentification.
Ajoutez un fichier appelé .env
dans votre répertoire racine et remplacez le code par ce qui suit.
REACT_APP_OKTA_ISSUER=https://{yourOktaDomain}/oauth2/default
REACT_APP_OKTA_CLIENTID={yourClientID}
REACT_APP_FIREBASE_APIKEY={yourFirebaseAPIKey}
REACT_APP_FIREBASE_AUTHDOMAIN={yourFirebaseAuthDomain}
REACT_APP_FIREBASE_PROJECTID={yourFirebaseProjectID}
REACT_APP_FIREBASE_STORAGEBUCKET={yourFirebaseStorageBucket}
REACT_APP_FIREBASE_MESSAGINGSENDERID={yourFirebaseMessagingSenderID}
REACT_APP_FIREBASE_APPID={yourFirebaseAppID}
REACT_APP_ENV=production
Vous avez obtenu les valeurs Okta lors de la création de votre application à l'aide de l'interface de ligne de commande Okta. Votre domaine Okta fait partie de l'émetteur. Les valeurs Firebase proviennent de la configuration que vous avez copiée lors de la première création de votre application.
Il existe actuellement une erreur connue dans React 18 avec la bibliothèque Okta React où plusieurs rendus peuvent entraîner un message d'erreur dans l' oktaAuth
objet. Le travail sur la correction de cette erreur est en cours. En attendant, vous pouvez contourner ce problème en désactivant React strict
. Remplacez le code de votre index.js
fichier par le code suivant.
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<App />
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
Ensuite, ouvrez votre App.js
fichier et remplacez le code par ce qui suit.
import "./App.css";
import { BrowserRouter as Router } from "react-router-dom";
import AppWithRouterAccess from "./AppWithRouterAccess";
import 'bootstrap/dist/css/bootstrap.min.css';
function App() {
return (
<Router>
<AppWithRouterAccess />
</Router>
);
}
export default App;
Vous remplacez le code par défaut par un Router
et un AppWithRouterAccess
que vous écrirez ensuite. Ouvrez un nouveau fichier appelé AppWithRouterAccess.jsx
et ajoutez le code suivant.
import "./App.css";
import { Route, useHistory } from "react-router-dom";
import { OktaAuth, toRelativeUrl } from "@okta/okta-auth-js";
import { Security, LoginCallback } from "@okta/okta-react";
import Home from "./Home";
const {
REACT_APP_OKTA_ISSUER,
REACT_APP_OKTA_CLIENTID
} = process.env;
const oktaAuth = new OktaAuth({
issuer: REACT_APP_OKTA_ISSUER,
clientId: REACT_APP_OKTA_CLIENTID,
redirectUri: window.location.origin + "/login/callback",
scopes: ['openid', 'profile', 'email']
});
function AppWithRouterAccess() {
const history = useHistory();
const restoreOriginalUri = async (_oktaAuth, originalUri) => {
history.replace(toRelativeUrl(originalUri || "/", window.location.origin));
};
return (
<Security oktaAuth={oktaAuth} restoreOriginalUri={restoreOriginalUri}>
<Route path="/" component={Home} />
<Route path="/login/callback" component={LoginCallback} />
</Security>
);
}
export default AppWithRouterAccess;
Ce fichier définira vos itinéraires et établira l' /login/callback
itinéraire permettant à Okta de gérer la signature de vos utilisateurs.
Enfin, ajoutez le Home.jsx
fichier à votre application avec le code suivant.
import React, { useState } from "react";
import { useOktaAuth } from "@okta/okta-react";
import { initializeApp } from "firebase/app";
import { getAuth, signInWithCustomToken, signOut } from "firebase/auth";
import {
getFunctions,
httpsCallable,
connectFunctionsEmulator,
} from "firebase/functions";
function Home() {
const [reportCardData, setReportCardData] = useState();
const [selectedSemester, setSelectedSemester] = useState("Spring 2022");
const { oktaAuth, authState } = useOktaAuth();
const login = async () => oktaAuth.signInWithRedirect();
const logout = async () => {
signOut(auth);
oktaAuth.signOut("/");
};
const {
REACT_APP_FIREBASE_APIKEY,
REACT_APP_FIREBASE_AUTHDOMAIN,
REACT_APP_FIREBASE_PROJECTID,
REACT_APP_FIREBASE_STORAGEBUCKET,
REACT_APP_FIREBASE_MESSAGINGSENDERID,
REACT_APP_FIREBASE_APPID,
REACT_APP_ENV,
} = process.env;
const firebaseConfig = {
apiKey: REACT_APP_FIREBASE_APIKEY,
authDomain: REACT_APP_FIREBASE_AUTHDOMAIN,
projectId: REACT_APP_FIREBASE_PROJECTID,
storageBucket: REACT_APP_FIREBASE_STORAGEBUCKET,
messagingSenderId: REACT_APP_FIREBASE_MESSAGINGSENDERID,
appId: REACT_APP_FIREBASE_APPID,
};
const app = initializeApp(firebaseConfig);
const functions = getFunctions(app);
const auth = getAuth();
if (REACT_APP_ENV === "development") {
connectFunctionsEmulator(functions, "localhost", 5001);
}
const getGrades = async () => {
const getGradesCall = httpsCallable(functions, "getGrades");
const resp = await getGradesCall({
name: selectedSemester.split(" ")[0],
year: selectedSemester.split(" ")[1],
});
setReportCardData(resp.data);
};
const exchangeOktaTokenForFirebaseToken = async () => {
const exchangeToken = httpsCallable(
functions,
"exchangeOktaTokenForFirebaseToken"
);
const resp = await exchangeToken({
accessToken: authState.accessToken.accessToken
});
await signInWithCustomToken(auth, resp.data.firebaseToken);
};
if (authState?.isAuthenticated) {
exchangeOktaTokenForFirebaseToken();
}
return (
<div className="App">
<main role="main" className="inner cover container">
<nav className="navbar navbar-expand-lg navbar-light bg-light ">
<ul className="nav navbar-nav ml-auto navbar-right ms-auto">
<li>
{auth?.currentUser && (
<button
className="btn btn-outline-secondary my-2 my-sm-0"
onClick={logout}
>
Logout
</button>
)}
{!auth?.currentUser && (
<button className="btn btn-outline-secondary" onClick={login}>
Login
</button>
)}
</li>
</ul>
</nav>
{!auth?.currentUser && (
<div>
<p className="lead">
In order to use this application you must be logged into your Okta
account
</p>
<p className="lead">
<button className="btn btn-primary" onClick={login}>
Login
</button>
</p>
</div>
)}
{auth?.currentUser && (
<div>
<h1 className="cover-heading">
Please select a semester to get your report card
</h1>
<div className="row">
<div className="col-2">
<select
className="form-select"
value={selectedSemester}
onChange={(e) => {
setSelectedSemester(e.target.value);
}}
>
<option value="Fall 2021">Fall 2021</option>
<option value="Spring 2021">Spring 2021</option>
<option value="Fall 2022">Fall 2022</option>
<option value="Spring 2022">Spring 2022</option>
</select>
</div>
<div className="col-2">
<button className="btn btn-primary" onClick={getGrades}>
Get Grades
</button>
</div>
</div>
{reportCardData && (
<>
<p>
<b>Name: </b> {reportCardData.name}
</p>
<p>
<b>School: </b> {reportCardData.school}
</p>
<p>
<b>Semester: </b> {reportCardData.semester} -{" "}
{reportCardData.year}
</p>
<table className="table table-striped">
<thead>
<tr>
<th className="text-start"> Course </th>
<th> Score </th>
<th> Letter Grade </th>
</tr>
</thead>
<tbody>
{reportCardData.grades.map((grade, i) => {
return (
<tr key={i}>
<td className="text-start">{grade.course}</td>
<td>{grade.score}</td>
<td>{grade.letterGrade}</td>
</tr>
);
})}
</tbody>
</table>
</>
)}
</div>
)}
<footer
className="bg-light text-center fixed-bottom"
style={{
width: "100%",
padding: "0 15px",
}}
>
<p>
A Small demo using <a href="https://developer.okta.com/">Okta</a> to
Secure an{" "}
<a href="https://firebase.google.com/">
Firebase hosted application{" "}
</a>{" "}
with a serverless{" "}
<a href="https://firebase.google.com/docs/functions">function</a>
</p>
<p>
By <a href="https://github.com/nickolasfisher">Nik Fisher</a>
</p>
</footer>
</main>
</div>
);
}
export default Home;
Cette page gérera à la fois les états authentifiés et non authentifiés. Si l'utilisateur n'est pas authentifié, un écran lui demandant de le faire lui est présenté. Si l'utilisateur est authentifié, il peut le faire getGrades
en sélectionnant un semestre dans la liste déroulante et en appelant le serveur.
La getGrades
fonction garantit que l'utilisateur est authentifié à l'aide de la fonction d'authentification intégrée dans Firebase. Firebase s'intègre également aux jetons d'authentification de fournisseurs tels qu'Okta. Pour utiliser cette fonctionnalité, vous créerez un jeton d'authentification Firebase à l'aide d'un jeton d'authentification Okta. Okta renvoie un accessToken
au client lorsque l'utilisateur se connecte. Le client transmet ensuite le accessToken
à une fonction Firebase appelée exchangeOktaTokenForFirebaseToken
. Dans cette fonction Cloud pour Firebase, vous vérifiez le jeton et renvoyez un jeton Firebase pour connecter l'utilisateur. Ensuite, les appels ultérieurs aux fonctions traiteront cet utilisateur comme étant connecté à Firebase.
À ce stade, vous pouvez utiliser la npm run start
commande pour exécuter votre application localement. Vous verrez quelques erreurs de console de Firebase et vous verrez des boutons de connexion . Notez que vous pouvez maintenant vous authentifier auprès d'Okta, mais que le processus de connexion n'appelle pas encore Firebase, votre connexion est donc toujours incomplète.
Vous êtes maintenant prêt à préparer votre application pour Firebase. Si vous ne l'avez pas encore fait, veuillez installer la CLI Firebase.
npm install -g firebase-tools@11.1.0
Pour vous connecter avec votre compte Google, vous devrez peut-être exécuter firebase login
.
Ensuite, exécutez la commande firebase init
pour lancer l'initialisation de votre projet.
Sélectionnez les deux fonctionnalités suivantes :
Sélectionnez Utiliser un projet existant et sélectionnez votre okta-firebase-{ID}
projet
Après un moment, vous verrez des invites pour configurer les fonctions Firebase. Sélectionnez les options suivantes :
Ensuite, sélectionnez les options suivantes pour configurer l'hébergement.
Avant de déployer votre application, vous devez exécuter la build
commande sur votre application React pour la préparer correctement. En configurant votre application en tant que SPA, vous indiquez à la CLI Firebase de modifier la configuration pour rediriger vers /index.html
.
Vous devriez remarquer qu'un nouveau dossier appelé functions
a été ajouté à votre répertoire. Là, vous verrez des éléments de configuration Firebase et un fichier appelé index.js
. Vous allez ajouter le code pour deux fonctions.
Tout d'abord, vous en aurez besoin d'un qui accepte un jeton Okta et renvoie un jeton Firebase à utiliser par le client. Pour vérifier le jeton, vous utiliserez le @okta/jwt-verifier
package d'Okta.
La deuxième fonction acceptera les arguments du client, à savoir le semestre, et les utilisera avec certaines informations du jeton pour créer des données de bulletin que le client utilisera pour créer le bulletin.
Commencez par accéder à votre répertoire de fonctions et installez vos dépendances.
cd functions
npm i @okta/jwt-verifier@2.3.0
Le @okta/jwt-verifier
vérifiera votre JWT d'Okta lors de l'appel de la exchangeOktaTokenForFirebaseToken
fonction.
Ensuite, copiez le fichier de clés que vous avez téléchargé précédemment à partir de la console Firebase et ajoutez-le à votre functions
dossier. Notez le nom, car vous en aurez besoin sous peu.
Ajoutez un fichier à votre functions
dossier appelé grades.js
et ajoutez le code suivant.
const getGrades = (user, semester) => {
return {
name: user.name,
school: getFakeUniversityName(user.email),
semester: semester.name,
year: semester.year,
grades: grades
.filter((r) => r.year == semester.year)
.filter((r) => r.semester == semester.name),
};
};
const getFakeUniversityName = (email) => {
const number = Math.floor(Math.random() * 2);
const domain = parseDomain(email);
switch (number) {
case 0:
return "University of " + domain;
case 1:
return domain + " State University";
default:
return "University of " + domain;
}
};
const parseDomain = (email) => {
const emailParts = email.split("@");
const domainParts = emailParts[1].split(".");
let name = "";
domainParts.forEach((part, i) => {
if (i > 0) {
name += " ";
}
if (i + 1 < domainParts.length) {
name += part.charAt(0).toUpperCase() + part.slice(1);
}
});
return name;
};
const grades = [
{
course: "Calculus 1",
score: 72,
letterGrade: "C",
year: 2021,
semester: "Fall",
},
{
course: "Intro to Ballroom Dance",
score: 94,
letterGrade: "A",
year: 2021,
semester: "Fall",
},
{
course: "Computer Science 101",
score: 65,
letterGrade: "F",
year: 2021,
semester: "Fall",
},
{
course: "Intro to Modern Physics",
score: 88,
letterGrade: "B",
year: 2021,
semester: "Fall",
},
{
course: "Calculus 2",
score: 84,
letterGrade: "C",
year: 2021,
semester: "Spring",
},
{
course: "Geometry",
score: 97,
letterGrade: "A",
year: 2021,
semester: "Spring",
},
{
course: "Computer Science 101",
score: 76,
letterGrade: "C",
year: 2021,
semester: "Spring",
},
{
course: "Physics II",
score: 88,
letterGrade: "B",
year: 2021,
semester: "Spring",
},
{
course: "Calculus 3",
score: 84,
letterGrade: "C",
year: 2022,
semester: "Fall",
},
{
course: "Abstract Algebra",
score: 97,
letterGrade: "A",
year: 2022,
semester: "Fall",
},
{
course: "Computer Science 102",
score: 76,
letterGrade: "C",
year: 2022,
semester: "Fall",
},
{
course: "Public Speaking",
score: 88,
letterGrade: "B",
year: 2022,
semester: "Fall",
},
{
course: "Adv Calculus",
score: 84,
letterGrade: "C",
year: 2022,
semester: "Spring",
},
{
course: "Geometry",
score: 97,
letterGrade: "A",
year: 2022,
semester: "Spring",
},
{
course: "Javascript in the Modern Web",
score: 76,
letterGrade: "C",
year: 2022,
semester: "Spring",
},
{
course: "Cryptography",
score: 88,
letterGrade: "B",
year: 2022,
semester: "Spring",
},
];
module.exports = { getGrades };
Tout d'abord, exchangeOktaTokenForFirebaseToken
fournira un jeton personnalisé de Firebase à utiliser dans votre application. Firebase vous permet de contrôler totalement votre authentification via la signInWithCustomToken
méthode que vous avez utilisée sur le client. Vous devez créer un jeton personnalisé à l'aide de votre compte de service. Vous avez précédemment téléchargé la définition de votre compte de service en tant que fichier JSON. Vous pouvez maintenant appeler createCustomToken
depuis votre auth
objet contre votre compte de service. Cette fonction nécessite un uid
et accepte éventuellement d'autres revendications que vous pourriez souhaiter ajouter. N'oubliez pas que Firebase réserve les noms de jeton .
Vous pouvez ensuite obtenir un jeton auprès du serveur d'autorisation Okta et le présenter à la fonction Firebase pour qu'il soit vérifié à l'aide du fichier OktaJwtVerifier
. Si le jeton Okta est valide, vous appellerez le point de userInfo
terminaison de votre serveur d'autorisation Okta pour obtenir des informations supplémentaires sur votre utilisateur. Vous pouvez inclure ces informations dans votre jeton Firebase en tant que revendications personnalisées. Ensuite, vous pouvez utiliser l' firebaseApp
objet pour créer votre jeton avec ces revendications. Vous renverrez ce jeton au client et vous vous connecterez avec.
Ensuite, vous avez la getGrades
fonction. Vous vérifiez context.auth
si l'utilisateur est connecté. Si ce n'est pas le cas, vous générez une erreur. Si c'est le cas, autorisez l'utilisateur à accéder aux données de notes dans ce fichier.
Il existe deux manières différentes de configurer des fonctions dans Firebase onCall
et onRequest
. onRequest
vous donne une forme plus brute de gestion de l'appel entrant. Vous devez configurer votre code CORS, votre authentification et toutes les bonnes choses dont le onCall
wrapper s'occupe pour vous. Par exemple, context.auth
est fourni parce que vous avez utilisé le onCall
, alors que onRequest
vous auriez besoin d'obtenir ces informations manuellement.
Vous êtes maintenant prêt à tester votre application localement via l'émulateur Firebase. L'émulateur fera en sorte que vos services puissent communiquer comme s'ils étaient déployés sur Firebase.
Tout d'abord, éditez votre .env
fichier pour le remplacer REACT_APP_ENV=production
par REACT_APP_ENV=development
. Cette modification indique à l'application de se connecter à l'émulateur. Ensuite, exécutez les commandes suivantes dans le répertoire racine de votre projet.
npm run build
firebase emulators:start
Tout d'abord, vous devez créer votre application car Firebase s'attend à ce que votre application se trouve dans le build
répertoire que vous avez configuré précédemment. Ensuite, il créera un émulateur et déploiera votre fonction et votre application Web sur cet émulateur. Par défaut, l'application Web se déploie localhost:5000
plutôt que l'habituel localhost:3000
.
Si vous constatez que vous avez des conflits avec les ports par défaut utilisés par Firebase, vous pouvez mettre à jour les firebase.json
entrées de fichier pour emulators.functions.port
et emulators.hosting.port
vers les ports dont vous disposez. Voir ci-dessous pour un exemple firebase.json
de fichier qui utilise le port 5002 pour l'hébergement et 5001 pour les fonctions.
{
"hosting": {
"public": "build",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
},
"functions": {
"source": "functions"
},
"emulators": {
"functions": {
"port": 5001
},
"hosting": {
"port": 5002
},
"ui": {
"enabled": false
}
}
}
Vous devrez ouvrir la console d'administration Okta et accéder à votre application Okta pour ajouter ces ports à la liste d'autorisation.
Ouvrez le portail des développeurs Okta et connectez-vous à Okta . Appuyez ensuite sur Admin pour lancer la console d'administration.
Accédez à Applications > Applications et recherchez votre application Okta pour ce projet. Sélectionnez-le pour le modifier. Dans l' onglet Général , modifiez les paramètres généraux avec les nouveaux ports. Par exemple, si votre port d'hébergement Firebase est 5000, ajoutez http://localhost:5000/login/callback
aux URI de redirection de connexion et http://localhost:5000
à vos URI de redirection de déconnexion . Mettez à jour le numéro de port en fonction des paramètres de votre émulateur Firebase et enregistrez.
Il y a un autre endroit pour ajouter le nouveau port dans la console d'administration Okta. Vous ajouterez le port en tant qu'origine approuvée afin que votre application puisse terminer le processus de déconnexion. Accédez à Sécurité > API et ouvrez l' onglet Origines approuvées. Appuyez sur le bouton + Ajouter une origine et ajoutez la nouvelle URL avec le port, par exemple http://localhost:5000/
. Cochez les cases Rediriger et CORS et enregistrez, puis revenez à votre application.
À ce stade, vous devriez pouvoir vous connecter à Okta, échanger votre jeton contre un jeton Firebase, sélectionner un semestre et cliquer sur Obtenir des notes pour voir votre bulletin généré.
Une fois que cela fonctionne, vous êtes prêt à déployer votre application sur Firebase. Tout d'abord, définissez votre .env
entrée pour REACT_APP_ENV
revenir à production
si vous l'aviez définie sur development
. Vous devrez peut-être exécuter la npm run build
commande une fois de plus au cas où vous auriez apporté des modifications ou des modifications. Une fois terminé, exécutez la commande firebase deploy
à partir de votre répertoire racine.
Après avoir terminé cette étape, votre CLI fournira une URL à votre application. Vous devriez voir votre application s'exécuter sur Firebase si vous cliquez dessus. Mais, Okta ne fonctionnera pas à ce stade. Vous devez revenir à votre portail d'administration Okta, sous votre application, et ajouter {yourFirebaseDomain}/login/callback
à vos URI de redirection de connexion , {yourFirebaseDomain}
à vos URI de redirection de déconnexion dans l' onglet Paramètres généraux de votre application Okta, et ajouter {yourFirebaseDomain} en tant que Trusted Origine
Revenez maintenant à votre application dans Firebase et cliquez sur Se connecter pour vous assurer qu'Okta est correctement connecté. Une fois connecté, vous devriez pouvoir sélectionner un semestre et cliquer sur Obtenir les notes pour voir votre bulletin généré.
Lien : https://developer.okta.com/blog/2022/06/27/react-firebase-serverless
#firebase #react #serverless
1659968400
Firebase is an exciting cloud platform from Google available to businesses today. Firebase connects everything from simple static websites to IoT devices to AI and machine learning platforms. The platform provides various services to facilitate these connections, like storage and authentication.
In this tutorial, you will learn about two core Firebase products: Cloud Functions for Firebase and Firebase Hosting. Hosting is for deploying static web applications. Functions are the Firebase serverless platform. You will create a static application using React that authenticates users via Okta’s React library. After obtaining an access token from Okta’s authorization server, you will use a Firebase function to exchange the Okta token for a Firebase token and sign in the user using Firebase’s authentication structure. You will obtain additional user information by calling the userInfo
endpoint on your Okta authorization server and including that data in your Firebase token. Finally, you will create another function endpoint to handle a simple HTTP request that requires an authenticated user.
See more at: https://developer.okta.com/blog/2022/06/27/react-firebase-serverless
#firebase #react #serverless
1659961140
Firebase 是 Google 提供的令人興奮的雲平台,如今可供企業使用。Firebase 連接了從簡單的靜態網站到物聯網設備再到人工智能和機器學習平台的一切。該平台提供各種服務來促進這些連接,例如存儲和身份驗證。
在本教程中,您將了解兩個核心 Firebase 產品:Firebase 的 Cloud Functions 和 Firebase 託管。託管用於部署靜態 Web 應用程序。函數是 Firebase 無服務器平台。您將使用 React 創建一個靜態應用程序,該應用程序通過 Okta 的 React 庫對用戶進行身份驗證。從 Okta 的授權服務器獲取訪問令牌後,您將使用 Firebase 函數將 Okta 令牌交換為 Firebase 令牌,並使用 Firebase 的身份驗證結構登錄用戶。您將通過調用userInfo
Okta 授權服務器上的端點並將該數據包含在您的 Firebase 令牌中來獲取其他用戶信息。最後,您將創建另一個函數端點來處理需要經過身份驗證的用戶的簡單 HTTP 請求。
構建應用程序後,您將使用 Firebase CLI 將其部署到 Firebase 平台以供公眾使用。
在開始之前,您需要一個免費的 Okta 開發者帳戶。安裝Okta CLI並運行okta register
以註冊一個新帳戶。如果您已經有一個帳戶,請運行okta login
. 然後,運行okta apps create
。選擇默認應用名稱,或根據需要進行更改。選擇Single-Page App並按Enter。
用於http://localhost:3000/login/callback
重定向 URI 並接受默認的註銷重定向 URI http://localhost:3000/login
。
接下來,打開Firebase 控制台並單擊Add Project。給你的項目起個名字,最好是okta-firebase
. 現在,您可以關閉分析並創建項目。完成後,您將能夠訪問項目儀表板。
首先,單擊屏幕底部Spark選項旁邊的升級按鈕。將您的計劃更改為 Blaze,如果您願意,可以設置 1 美元的計費預算,以便在您產生費用時通知您。Blaze 是現收現付的,而且對於業餘愛好項目的費率相當慷慨。您目前不應該產生任何費用,但如果您這樣做,預算會通知您。
單擊項目概覽旁邊的設置輪,然後單擊項目設置。在概述頁面的底部,有一個提示選擇一個平台以開始並選擇網絡應用程序(它看起來像</>)。為您的應用指定暱稱okta-firebase-demo
,然後選擇Also setup Firebase Hosting for this app。單擊註冊應用程序,稍後您將看到一些用於設置 Firebase 應用程序的 JavaScript 代碼。
保留此信息,因為您將在您的應用程序中需要它。單擊嚮導的其餘部分並返回到您的控制台。再次轉到項目設置部分並導航到服務帳戶選項卡。單擊生成新私鑰並下載該文件。您很快就會在 Firebase 函數中用到它。
最後,單擊側導航中的Build > Authentication並單擊Get Started。按下Get Started按鈕會生成使用身份驗證功能所需的Web API 密鑰。
接下來,創建您的 React 應用程序。
npx create-react-app@5 okta-firebase
cd okta-firebase
npx 命令將為您搭建一個新的 React 版本 18 應用程序。
接下來,您將需要安裝一些依賴項來幫助您。
npm i @okta/okta-react@6.4.3
npm i @okta/okta-auth-js@6.2.0
npm i react-router-dom@5.3.0
npm i bootstrap@5.1.3
npm i firebase@9.8.1
首先,您要安裝該@okta/okta-react
軟件包以幫助驗證用戶並從 Okta 授權服務器獲取令牌。這個包將幫助您訪問身份驗證狀態,將用戶引導到 Okta 登錄頁面,並處理任何回調。
@okta/okta-react
依賴@okta/okta-auth-js
包,所以你需要安裝它。
接下來,您要安裝react-router-dom
. 該軟件包將為您設置回調路由以及您可能需要的任何其他路由。
最後,您將使用該firebase
包調用 Firebase 中的各種平台功能,例如函數和身份驗證。
在根目錄中添加一個名為的文件.env
,並將代碼替換為以下內容。
REACT_APP_OKTA_ISSUER=https://{yourOktaDomain}/oauth2/default
REACT_APP_OKTA_CLIENTID={yourClientID}
REACT_APP_FIREBASE_APIKEY={yourFirebaseAPIKey}
REACT_APP_FIREBASE_AUTHDOMAIN={yourFirebaseAuthDomain}
REACT_APP_FIREBASE_PROJECTID={yourFirebaseProjectID}
REACT_APP_FIREBASE_STORAGEBUCKET={yourFirebaseStorageBucket}
REACT_APP_FIREBASE_MESSAGINGSENDERID={yourFirebaseMessagingSenderID}
REACT_APP_FIREBASE_APPID={yourFirebaseAppID}
REACT_APP_ENV=production
您在之前使用 Okta CLI 創建應用程序時獲得了 Okta 值。您的 Okta 域是頒發者的一部分。Firebase 值來自您在首次創建應用程序時復制的配置。
目前在使用 Okta React 庫的 React 18 中存在一個已知錯誤,其中多次重新渲染可能導致對oktaAuth
像中出現錯誤消息。修復此錯誤的工作正在進行中。strict
同時,您可以通過將 React 退出模式來解決它。將index.js
文件中的代碼替換為以下代碼。
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<App />
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
接下來,打開您的App.js
文件並將代碼替換為以下內容。
import "./App.css";
import { BrowserRouter as Router } from "react-router-dom";
import AppWithRouterAccess from "./AppWithRouterAccess";
import 'bootstrap/dist/css/bootstrap.min.css';
function App() {
return (
<Router>
<AppWithRouterAccess />
</Router>
);
}
export default App;
您將用接下來編寫的 aRouter
和 an替換默認代碼。AppWithRouterAccess
打開一個名為的新文件AppWithRouterAccess.jsx
並添加以下代碼。
import "./App.css";
import { Route, useHistory } from "react-router-dom";
import { OktaAuth, toRelativeUrl } from "@okta/okta-auth-js";
import { Security, LoginCallback } from "@okta/okta-react";
import Home from "./Home";
const {
REACT_APP_OKTA_ISSUER,
REACT_APP_OKTA_CLIENTID
} = process.env;
const oktaAuth = new OktaAuth({
issuer: REACT_APP_OKTA_ISSUER,
clientId: REACT_APP_OKTA_CLIENTID,
redirectUri: window.location.origin + "/login/callback",
scopes: ['openid', 'profile', 'email']
});
function AppWithRouterAccess() {
const history = useHistory();
const restoreOriginalUri = async (_oktaAuth, originalUri) => {
history.replace(toRelativeUrl(originalUri || "/", window.location.origin));
};
return (
<Security oktaAuth={oktaAuth} restoreOriginalUri={restoreOriginalUri}>
<Route path="/" component={Home} />
<Route path="/login/callback" component={LoginCallback} />
</Security>
);
}
export default AppWithRouterAccess;
該文件將定義您的路由並/login/callback
為 Okta 建立路由以處理您的用戶登錄。
最後,Home.jsx
使用以下代碼將該文件添加到您的應用程序中。
import React, { useState } from "react";
import { useOktaAuth } from "@okta/okta-react";
import { initializeApp } from "firebase/app";
import { getAuth, signInWithCustomToken, signOut } from "firebase/auth";
import {
getFunctions,
httpsCallable,
connectFunctionsEmulator,
} from "firebase/functions";
function Home() {
const [reportCardData, setReportCardData] = useState();
const [selectedSemester, setSelectedSemester] = useState("Spring 2022");
const { oktaAuth, authState } = useOktaAuth();
const login = async () => oktaAuth.signInWithRedirect();
const logout = async () => {
signOut(auth);
oktaAuth.signOut("/");
};
const {
REACT_APP_FIREBASE_APIKEY,
REACT_APP_FIREBASE_AUTHDOMAIN,
REACT_APP_FIREBASE_PROJECTID,
REACT_APP_FIREBASE_STORAGEBUCKET,
REACT_APP_FIREBASE_MESSAGINGSENDERID,
REACT_APP_FIREBASE_APPID,
REACT_APP_ENV,
} = process.env;
const firebaseConfig = {
apiKey: REACT_APP_FIREBASE_APIKEY,
authDomain: REACT_APP_FIREBASE_AUTHDOMAIN,
projectId: REACT_APP_FIREBASE_PROJECTID,
storageBucket: REACT_APP_FIREBASE_STORAGEBUCKET,
messagingSenderId: REACT_APP_FIREBASE_MESSAGINGSENDERID,
appId: REACT_APP_FIREBASE_APPID,
};
const app = initializeApp(firebaseConfig);
const functions = getFunctions(app);
const auth = getAuth();
if (REACT_APP_ENV === "development") {
connectFunctionsEmulator(functions, "localhost", 5001);
}
const getGrades = async () => {
const getGradesCall = httpsCallable(functions, "getGrades");
const resp = await getGradesCall({
name: selectedSemester.split(" ")[0],
year: selectedSemester.split(" ")[1],
});
setReportCardData(resp.data);
};
const exchangeOktaTokenForFirebaseToken = async () => {
const exchangeToken = httpsCallable(
functions,
"exchangeOktaTokenForFirebaseToken"
);
const resp = await exchangeToken({
accessToken: authState.accessToken.accessToken
});
await signInWithCustomToken(auth, resp.data.firebaseToken);
};
if (authState?.isAuthenticated) {
exchangeOktaTokenForFirebaseToken();
}
return (
<div className="App">
<main role="main" className="inner cover container">
<nav className="navbar navbar-expand-lg navbar-light bg-light ">
<ul className="nav navbar-nav ml-auto navbar-right ms-auto">
<li>
{auth?.currentUser && (
<button
className="btn btn-outline-secondary my-2 my-sm-0"
onClick={logout}
>
Logout
</button>
)}
{!auth?.currentUser && (
<button className="btn btn-outline-secondary" onClick={login}>
Login
</button>
)}
</li>
</ul>
</nav>
{!auth?.currentUser && (
<div>
<p className="lead">
In order to use this application you must be logged into your Okta
account
</p>
<p className="lead">
<button className="btn btn-primary" onClick={login}>
Login
</button>
</p>
</div>
)}
{auth?.currentUser && (
<div>
<h1 className="cover-heading">
Please select a semester to get your report card
</h1>
<div className="row">
<div className="col-2">
<select
className="form-select"
value={selectedSemester}
onChange={(e) => {
setSelectedSemester(e.target.value);
}}
>
<option value="Fall 2021">Fall 2021</option>
<option value="Spring 2021">Spring 2021</option>
<option value="Fall 2022">Fall 2022</option>
<option value="Spring 2022">Spring 2022</option>
</select>
</div>
<div className="col-2">
<button className="btn btn-primary" onClick={getGrades}>
Get Grades
</button>
</div>
</div>
{reportCardData && (
<>
<p>
<b>Name: </b> {reportCardData.name}
</p>
<p>
<b>School: </b> {reportCardData.school}
</p>
<p>
<b>Semester: </b> {reportCardData.semester} -{" "}
{reportCardData.year}
</p>
<table className="table table-striped">
<thead>
<tr>
<th className="text-start"> Course </th>
<th> Score </th>
<th> Letter Grade </th>
</tr>
</thead>
<tbody>
{reportCardData.grades.map((grade, i) => {
return (
<tr key={i}>
<td className="text-start">{grade.course}</td>
<td>{grade.score}</td>
<td>{grade.letterGrade}</td>
</tr>
);
})}
</tbody>
</table>
</>
)}
</div>
)}
<footer
className="bg-light text-center fixed-bottom"
style={{
width: "100%",
padding: "0 15px",
}}
>
<p>
A Small demo using <a href="https://developer.okta.com/">Okta</a> to
Secure an{" "}
<a href="https://firebase.google.com/">
Firebase hosted application{" "}
</a>{" "}
with a serverless{" "}
<a href="https://firebase.google.com/docs/functions">function</a>
</p>
<p>
By <a href="https://github.com/nickolasfisher">Nik Fisher</a>
</p>
</footer>
</main>
</div>
);
}
export default Home;
此頁面將處理經過身份驗證和未經身份驗證的狀態。如果用戶未通過身份驗證,則會向他們顯示一個屏幕,要求他們這樣做。如果用戶通過身份驗證,他們可以getGrades
通過從下拉列表中選擇學期並調用服務器。
該getGrades
函數可確保使用 Firebase 中的內置身份驗證功能對用戶進行身份驗證。Firebase 還與來自 Okta 等提供商的身份驗證令牌集成。要利用此功能,您將使用 Okta 身份驗證令牌生成 Firebase 身份驗證令牌。當用戶登錄時, OktaaccessToken
向客戶端返回一個。然後客戶端將 傳遞accessToken
給一個名為 的 Firebase 函數exchangeOktaTokenForFirebaseToken
。在此 Cloud Function for Firebase 中,您驗證令牌並返回 Firebase 令牌以使用戶登錄。隨後對函數的調用將把該用戶視為已登錄到 Firebase。
此時,您可以使用npm run start
命令在本地運行您的應用程序。您會看到一些來自 Firebase 的控制台錯誤,並且您會看到登錄按鈕。請注意,您現在可以使用 Okta 進行身份驗證,但登錄過程尚未調用 Firebase,因此您的登錄仍然不完整。
現在您已準備好為 Firebase 準備應用程序。如果您還沒有這樣做,請安裝 Firebase CLI。
npm install -g firebase-tools@11.1.0
要使用您的 Google 帳戶登錄,您可能需要運行firebase login
.
接下來,運行命令firebase init
來開始你的項目的初始化。
選擇以下兩個功能:
選擇使用現有項目並選擇您的okta-firebase-{ID}
項目
片刻之後,您會看到設置 Firebase 功能的提示。選擇以下選項:
接下來,選擇以下選項來設置託管。
在部署您的應用程序之前,您必須build
在您的 React 應用程序上運行命令以正確準備它。通過將您的應用配置為 SPA,您可以告訴 Firebase CLI 編輯配置以重定向到/index.html
.
您應該注意到一個名為的新文件夾functions
已添加到您的目錄中。在那裡,您將看到一些 Firebase 配置內容和一個名為index.js
. 您將為兩個函數添加代碼。
首先,您需要一個接受 Okta 令牌並返回 Firebase 令牌供客戶端使用的令牌。要驗證令牌,您將使用@okta/jwt-verifier
來自 Okta 的包。
第二個函數將接受來自客戶端的參數,即學期,並將其與令牌中的一些信息一起使用來構建報告卡數據,供客戶用於創建報告卡。
首先導航到您的函數目錄並安裝您的依賴項。
cd functions
npm i @okta/jwt-verifier@2.3.0
調用該函數@okta/jwt-verifier
時,它將從 Okta 驗證您的 JWT 。exchangeOktaTokenForFirebaseToken
接下來,複製您之前從 Firebase 控制台下載的密鑰文件並將其添加到您的functions
文件夾中。記下名稱,因為您很快就會需要它。
將文件添加到functions
名為的文件夾grades.js
並添加以下代碼。
const getGrades = (user, semester) => {
return {
name: user.name,
school: getFakeUniversityName(user.email),
semester: semester.name,
year: semester.year,
grades: grades
.filter((r) => r.year == semester.year)
.filter((r) => r.semester == semester.name),
};
};
const getFakeUniversityName = (email) => {
const number = Math.floor(Math.random() * 2);
const domain = parseDomain(email);
switch (number) {
case 0:
return "University of " + domain;
case 1:
return domain + " State University";
default:
return "University of " + domain;
}
};
const parseDomain = (email) => {
const emailParts = email.split("@");
const domainParts = emailParts[1].split(".");
let name = "";
domainParts.forEach((part, i) => {
if (i > 0) {
name += " ";
}
if (i + 1 < domainParts.length) {
name += part.charAt(0).toUpperCase() + part.slice(1);
}
});
return name;
};
const grades = [
{
course: "Calculus 1",
score: 72,
letterGrade: "C",
year: 2021,
semester: "Fall",
},
{
course: "Intro to Ballroom Dance",
score: 94,
letterGrade: "A",
year: 2021,
semester: "Fall",
},
{
course: "Computer Science 101",
score: 65,
letterGrade: "F",
year: 2021,
semester: "Fall",
},
{
course: "Intro to Modern Physics",
score: 88,
letterGrade: "B",
year: 2021,
semester: "Fall",
},
{
course: "Calculus 2",
score: 84,
letterGrade: "C",
year: 2021,
semester: "Spring",
},
{
course: "Geometry",
score: 97,
letterGrade: "A",
year: 2021,
semester: "Spring",
},
{
course: "Computer Science 101",
score: 76,
letterGrade: "C",
year: 2021,
semester: "Spring",
},
{
course: "Physics II",
score: 88,
letterGrade: "B",
year: 2021,
semester: "Spring",
},
{
course: "Calculus 3",
score: 84,
letterGrade: "C",
year: 2022,
semester: "Fall",
},
{
course: "Abstract Algebra",
score: 97,
letterGrade: "A",
year: 2022,
semester: "Fall",
},
{
course: "Computer Science 102",
score: 76,
letterGrade: "C",
year: 2022,
semester: "Fall",
},
{
course: "Public Speaking",
score: 88,
letterGrade: "B",
year: 2022,
semester: "Fall",
},
{
course: "Adv Calculus",
score: 84,
letterGrade: "C",
year: 2022,
semester: "Spring",
},
{
course: "Geometry",
score: 97,
letterGrade: "A",
year: 2022,
semester: "Spring",
},
{
course: "Javascript in the Modern Web",
score: 76,
letterGrade: "C",
year: 2022,
semester: "Spring",
},
{
course: "Cryptography",
score: 88,
letterGrade: "B",
year: 2022,
semester: "Spring",
},
];
module.exports = { getGrades };
首先,exchangeOktaTokenForFirebaseToken
將提供來自 Firebase 的自定義令牌以在您的應用程序中使用。signInWithCustomToken
Firebase 允許您通過在客戶端上使用的方法完全控制您的身份驗證。您需要使用您的服務帳戶創建自定義令牌。您之前已將服務帳戶定義下載為 JSON 文件。現在您可以createCustomToken
從您的auth
對象調用您的服務帳戶。此功能需要 auid
並且可以選擇接受您可能希望添加的其他聲明。請注意Firebase 會保留令牌名稱。
然後,您可以從 Okta 授權服務器獲取令牌並將其提供給 Firebase 函數以使用OktaJwtVerifier
. 如果 Okta 令牌有效,您將調用 Okta 授權服務器的userInfo
端點以獲取有關您的用戶的其他信息。您可以將此信息作為其自定義聲明包含在您的 Firebase 令牌中。然後,您可以使用該firebaseApp
對象通過這些聲明創建您的令牌。您將將此令牌返回給客戶端並使用它登錄。
接下來,您擁有該getGrades
功能。您檢查context.auth
用戶是否已登錄。如果沒有,您將引發錯誤。如果是,則允許用戶訪問該文件中的成績數據。
在 Firebase 中設置函數有兩種不同的方法onCall
,onRequest
. onRequest
為您提供處理來電的更原始形式。您需要設置 CORS 代碼、身份驗證以及onCall
包裝器為您處理的所有好東西。例如,context.auth
提供是因為您使用了onCall
,而通過onRequest
您需要手動獲取此信息。
現在您已準備好通過 Firebase 模擬器在本地測試您的應用程序。模擬器將使您的服務可以像部署到 Firebase 一樣進行通信。
首先,編輯您的.env
文件以替換REACT_APP_ENV=production
為REACT_APP_ENV=development
. 此更改告訴應用程序連接到模擬器。接下來,在項目的根目錄中運行以下命令。
npm run build
firebase emulators:start
首先,您需要構建您的應用程序,因為 Firebase 期望您的應用程序位於build
您之前配置的目錄中。接下來,它將創建一個模擬器並將您的函數和 Web 應用程序部署到該模擬器。默認情況下,Web 應用程序部署到localhost:5000
而不是通常的localhost:3000
.
如果您發現您與 Firebase 使用的默認端口有衝突,您可以更新您可用的端口的文件firebase.json
條目。請參閱下面的示例文件,該文件使用端口 5002 進行託管,使用端口 5001 進行功能。emulators.functions.portemulators.hosting.portfirebase.json
{
"hosting": {
"public": "build",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
},
"functions": {
"source": "functions"
},
"emulators": {
"functions": {
"port": 5001
},
"hosting": {
"port": 5002
},
"ui": {
"enabled": false
}
}
}
您需要打開 Okta 管理控制台並導航到您的 Okta 應用程序以將這些端口添加到允許列表中。
打開Okta 開發人員門戶並登錄到 Okta。然後按Admin啟動管理控制台。
導航到應用程序>應用程序並找到此項目的 Okta 應用程序。選擇它進行編輯。在常規選項卡上,使用新端口編輯常規設置。例如,如果您的 Firebase 託管端口是 5000,請添加到http://localhost:5000/login/callback
Sign -in redirect URIs和Sign-out redirect URIs。根據您的 Firebase 模擬器設置更新端口號並保存。http://localhost:5000
在 Okta 管理控制台中還有一個地方可以添加新端口。您將端口添加為受信任的來源,以便您的應用程序可以完成註銷過程。導航到Security > API並打開Trusted Origins選項卡。按+ Add Origin按鈕並添加帶有端口的新 URL,例如http://localhost:5000/
. 選擇Redirect和CORS複選框並保存,然後返回到您的應用程序。
此時,您應該能夠登錄 Okta,將您的令牌換成 Firebase 令牌,選擇一個學期,然後單擊Get Grades以查看您的報告卡生成。
一旦成功,您就可以將應用程序部署到 Firebase。首先,如果您已將.env
條目設置為REACT_APP_ENV
,請將其設置為。如果您進行了任何編輯或更改,您可能需要再次運行該命令。完成後,從根目錄運行命令。productiondevelopmentnpm run buildfirebase deploy
完成此步驟後,您的 CLI 將為您的應用程序提供一個 URL。如果您單擊它,您應該會看到您的應用程序在 Firebase 上運行。但是,此時 Okta 將無法工作。您需要返回您的 Okta 管理門戶,在您的應用程序下,添加{yourFirebaseDomain}/login/callback
到您的Sign-in redirect URIs,{yourFirebaseDomain}
到您的Sign-out redirect URIs到您的 Okta 應用程序的General Settings選項卡,並將 {yourFirebaseDomain} 添加為Trusted起源
現在返回到您在 Firebase 中的應用程序並單擊登錄以確保 Okta 已正確連接。登錄後,您應該能夠選擇一個學期並單擊“獲取成績”以查看生成的成績單。
鏈接:https ://developer.okta.com/blog/2022/06/27/react-firebase-serverless
#firebase #react #serverless