1+
2+ using System ;
3+ using System . Collections ;
4+ using System . Collections . Generic ;
5+ using System . Text ;
6+ using MiniJSON ;
7+ using UnityEngine ;
8+ using UnityEngine . Networking ;
9+ namespace FirebaseREST
10+ {
11+ public class FirebaseAuth : MonoBehaviour
12+ {
13+ readonly string EMAIL_AUTH_URL = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=" + FirebaseSettings . WEB_API ;
14+ readonly string CUSTOM_TOKEN_AUTH_URL = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyCustomToken?key=" + FirebaseSettings . WEB_API ;
15+ readonly string REFRESH_TOKEN_URL = "https://securetoken.googleapis.com/v1/token?key=" + FirebaseSettings . WEB_API ;
16+ readonly string USER_INFO_URL = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/getAccountInfo?key=" + FirebaseSettings . WEB_API ;
17+ TokenData tokenData ;
18+
19+ public TokenData TokenData { get { return tokenData ; } set { this . tokenData = value ; } }
20+
21+ private static bool applicationIsQuitting = false ;
22+ private static FirebaseAuth _instance ;
23+ private static object _lock = new object ( ) ;
24+ public static FirebaseAuth Instance
25+ {
26+ get
27+ {
28+ if ( applicationIsQuitting )
29+ {
30+ return null ;
31+ }
32+
33+ lock ( _lock )
34+ {
35+ if ( _instance == null )
36+ {
37+ _instance = ( FirebaseAuth ) FindObjectOfType ( typeof ( FirebaseAuth ) ) ;
38+
39+ if ( FindObjectsOfType ( typeof ( FirebaseAuth ) ) . Length > 1 )
40+ {
41+ Debug . LogError ( "there should never be more than 1 singleton!" ) ;
42+ return _instance ;
43+ }
44+
45+ if ( _instance == null )
46+ {
47+ GameObject singleton = new GameObject ( ) ;
48+ _instance = singleton . AddComponent < FirebaseAuth > ( ) ;
49+ singleton . name = "(singleton) " + typeof ( FirebaseAuth ) . ToString ( ) ;
50+ DontDestroyOnLoad ( singleton ) ;
51+ Debug . Log ( typeof ( FirebaseAuth ) . ToString ( ) + " singleton created" ) ;
52+ }
53+ else
54+ {
55+ Debug . Log ( "instance already created: " + _instance . gameObject . name ) ;
56+ }
57+ }
58+ return _instance ;
59+ }
60+ }
61+ }
62+
63+ void OnDestroy ( )
64+ {
65+ applicationIsQuitting = true ;
66+ }
67+
68+ public string AccessToken
69+ {
70+ get
71+ {
72+ if ( tokenData == null )
73+ return null ;
74+ return tokenData . idToken ;
75+ }
76+ }
77+
78+ public bool IsSignedIn
79+ {
80+ get
81+ {
82+ return tokenData != null ;
83+ }
84+ }
85+
86+ void Awake ( )
87+ {
88+
89+ }
90+
91+ public void FetchUserInfo ( int timeout , Action < Response < List < UserData > > > OnComplete )
92+ {
93+ if ( tokenData == null )
94+ throw new Exception ( "User has not logged in" ) ;
95+ UnityWebRequestAsyncOperation op = StartRequest ( USER_INFO_URL , "POST" , new Dictionary < string , object > ( ) {
96+ { "idToken" , tokenData . idToken }
97+ } , timeout ) ;
98+ op . completed += ( ( ao ) => HandleFirebaseResponse ( op , ( res ) =>
99+ {
100+ Dictionary < string , object > map = Json . Deserialize ( res . data ) as Dictionary < string , object > ;
101+ List < object > userDatas = Json . Deserialize ( Json . Serialize ( map [ "users" ] ) ) as List < object > ;
102+ List < UserData > dataToReturn = new List < UserData > ( ) ;
103+ for ( int i = 0 ; i < userDatas . Count ; i ++ )
104+ {
105+ Dictionary < string , object > userMap = Json . Deserialize ( Json . Serialize ( userDatas [ i ] ) ) as Dictionary < string , object > ;
106+ UserData ud = new UserData ( ) ;
107+ ud . createdAt = userMap . ContainsKey ( "createdAt" ) ? long . Parse ( userMap [ "createdAt" ] . ToString ( ) ) : 0L ;
108+ ud . customAuth = userMap . ContainsKey ( "customAuth" ) ? bool . Parse ( userMap [ "customAuth" ] . ToString ( ) ) : false ;
109+ ud . disabled = userMap . ContainsKey ( "disabled" ) ? bool . Parse ( userMap [ "disabled" ] . ToString ( ) ) : false ;
110+ ud . displayName = userMap . ContainsKey ( "displayName" ) ? userMap [ "displayName" ] . ToString ( ) : null ;
111+ ud . email = userMap . ContainsKey ( "email" ) ? userMap [ "email" ] . ToString ( ) : null ;
112+ ud . emailVerified = userMap . ContainsKey ( "emailVerified" ) ? bool . Parse ( userMap [ "emailVerified" ] . ToString ( ) ) : false ;
113+ ud . lastLoginAt = userMap . ContainsKey ( "lastLoginAt" ) ? long . Parse ( userMap [ "lastLoginAt" ] . ToString ( ) ) : 0L ;
114+ ud . localId = userMap . ContainsKey ( "localId" ) ? userMap [ "localId" ] . ToString ( ) : null ;
115+ ud . passwordUpdatedAt = userMap . ContainsKey ( "passwordUpdatedAt" ) ? long . Parse ( userMap [ "passwordUpdatedAt" ] . ToString ( ) ) : 0L ;
116+ ud . photoUrl = userMap . ContainsKey ( "photoUrl" ) ? userMap [ "photoUrl" ] . ToString ( ) : null ;
117+ ud . validSince = userMap . ContainsKey ( "photoUrl" ) ? userMap [ "validSince" ] . ToString ( ) : null ;
118+ if ( userMap . ContainsKey ( "providerUserInfo" ) )
119+ {
120+ ud . providerUserInfo = new List < ProviderInfo > ( ) ;
121+ List < object > providers = Json . Deserialize ( Json . Serialize ( userMap [ "providerUserInfo" ] ) ) as List < object > ;
122+ for ( int j = 0 ; j < providers . Count ; j ++ )
123+ {
124+ ProviderInfo providerInfo = new ProviderInfo ( ) ;
125+ Dictionary < string , object > obj = Json . Deserialize ( Json . Serialize ( providers [ j ] ) ) as Dictionary < string , object > ;
126+ providerInfo . federatedId = obj [ "federatedId" ] . ToString ( ) ;
127+ providerInfo . providerId = obj [ "providerId" ] . ToString ( ) ;
128+ ud . providerUserInfo . Add ( providerInfo ) ;
129+ }
130+ }
131+ dataToReturn . Add ( ud ) ;
132+ }
133+ if ( OnComplete != null )
134+ OnComplete ( new Response < List < UserData > > ( "success" , true , res . code , dataToReturn ) ) ;
135+ } ) ) ;
136+ }
137+
138+ public void RefreshAccessToken ( int timeout , Action < Response < TokenData > > OnComplete )
139+ {
140+ if ( tokenData == null )
141+ throw new Exception ( "User has not logged in" ) ;
142+ UnityWebRequestAsyncOperation op = StartRequest ( REFRESH_TOKEN_URL , "POST" , new Dictionary < string , object > ( ) {
143+ { "grant_type" , "refresh_token" } , { "refresh_token" , tokenData . refreshToken }
144+ } , timeout ) ;
145+ op . completed += ( ( ao ) => HandleFirebaseResponse ( op , ( res ) =>
146+ {
147+ Dictionary < string , object > dataMap = Json . Deserialize ( op . webRequest . downloadHandler . text ) as Dictionary < string , object > ;
148+ this . tokenData = new TokenData ( ) ;
149+ tokenData . expiresIn = dataMap [ "expires_in" ] . ToString ( ) ;
150+ tokenData . idToken = dataMap [ "id_token" ] . ToString ( ) ;
151+ tokenData . refreshToken = dataMap [ "refresh_token" ] . ToString ( ) ;
152+ if ( OnComplete != null )
153+ OnComplete ( new Response < TokenData > ( "success" , true , ( int ) op . webRequest . responseCode , tokenData ) ) ;
154+ } ) ) ;
155+ }
156+
157+ public void SignInWithCustomToken ( string customToken , int timeout , Action < Response < TokenData > > OnComplete )
158+ {
159+ UnityWebRequestAsyncOperation op = StartRequest ( CUSTOM_TOKEN_AUTH_URL , "POST" , new Dictionary < string , object > ( ) {
160+ { "token" , customToken } , { "returnSecureToken" , true }
161+ } , timeout ) ;
162+ op . completed += ( ( ao ) => HandleFirebaseSignInResponse ( op , OnComplete ) ) ;
163+ }
164+
165+ public void SignInWithEmail ( string email , string password , int timeout , Action < Response < TokenData > > OnComplete )
166+ {
167+ UnityWebRequestAsyncOperation op = StartRequest ( EMAIL_AUTH_URL , "POST" , new Dictionary < string , object > ( ) {
168+ { "email" , email } , { "password" , password } , { "returnSecureToken" , true }
169+ } , timeout ) ;
170+ op . completed += ( ( ao ) => HandleFirebaseSignInResponse ( op , OnComplete ) ) ;
171+ }
172+
173+ UnityWebRequestAsyncOperation StartRequest ( string url , string requestMethod , Dictionary < string , object > data , int timeout )
174+ {
175+ UnityWebRequest webReq = new UnityWebRequest ( url , requestMethod ) ;
176+ webReq . downloadHandler = new DownloadHandlerBuffer ( ) ;
177+ byte [ ] bodyRaw = Encoding . UTF8 . GetBytes ( Json . Serialize ( data ) ) ;
178+ webReq . uploadHandler = new UploadHandlerRaw ( bodyRaw ) ;
179+ webReq . SetRequestHeader ( "Content-Type" , "application/json" ) ;
180+ webReq . timeout = timeout ;
181+ return webReq . SendWebRequest ( ) ;
182+ }
183+
184+ void HandleFirebaseSignInResponse ( UnityWebRequestAsyncOperation webReqOp , Action < Response < TokenData > > OnComplete )
185+ {
186+ if ( webReqOp . webRequest . isNetworkError )
187+ {
188+ if ( OnComplete != null )
189+ OnComplete ( new Response < TokenData > ( webReqOp . webRequest . error , false , 0 , null ) ) ;
190+ }
191+ else if ( webReqOp . webRequest . isHttpError )
192+ {
193+ Dictionary < string , object > res = Json . Deserialize ( webReqOp . webRequest . downloadHandler . text ) as Dictionary < string , object > ;
194+ Dictionary < string , object > errorObj = Json . Deserialize ( Json . Serialize ( res [ "error" ] ) ) as Dictionary < string , object > ;
195+ if ( OnComplete != null )
196+ OnComplete ( new Response < TokenData > ( errorObj [ "message" ] . ToString ( ) , false , int . Parse ( errorObj [ "code" ] . ToString ( ) ) , null ) ) ;
197+ }
198+ else
199+ {
200+ if ( OnComplete != null )
201+ {
202+ Dictionary < string , object > dataMap = Json . Deserialize ( webReqOp . webRequest . downloadHandler . text ) as Dictionary < string , object > ;
203+ this . tokenData = new TokenData ( ) ;
204+ tokenData . expiresIn = dataMap [ "expiresIn" ] . ToString ( ) ;
205+ tokenData . idToken = dataMap [ "idToken" ] . ToString ( ) ;
206+ tokenData . refreshToken = dataMap [ "refreshToken" ] . ToString ( ) ;
207+ OnComplete ( new Response < TokenData > ( "success" , true , ( int ) webReqOp . webRequest . responseCode , tokenData ) ) ;
208+ }
209+ }
210+ }
211+
212+ void HandleFirebaseResponse ( UnityWebRequestAsyncOperation webReqOp , Action < Response > OnComplete )
213+ {
214+ if ( webReqOp . webRequest . isNetworkError )
215+ {
216+ if ( OnComplete != null )
217+ OnComplete ( new Response ( webReqOp . webRequest . error , false , 0 , null ) ) ;
218+ }
219+ else if ( webReqOp . webRequest . isHttpError )
220+ {
221+ Dictionary < string , object > res = Json . Deserialize ( webReqOp . webRequest . downloadHandler . text ) as Dictionary < string , object > ;
222+ Dictionary < string , object > errorObj = Json . Deserialize ( Json . Serialize ( res [ "error" ] ) ) as Dictionary < string , object > ;
223+ if ( OnComplete != null )
224+ OnComplete ( new Response ( errorObj [ "message" ] . ToString ( ) , false , int . Parse ( errorObj [ "code" ] . ToString ( ) ) , null ) ) ;
225+ }
226+ else
227+ {
228+ if ( OnComplete != null )
229+ OnComplete ( new Response ( "success" , true , ( int ) webReqOp . webRequest . responseCode , webReqOp . webRequest . downloadHandler . text ) ) ;
230+ }
231+ }
232+ }
233+ }
0 commit comments