1
1
import { Provider , Inject , provide , Injectable , Optional } from '@angular/core' ;
2
+ import { Observable } from 'rxjs/Observable' ;
3
+ import { Observer } from 'rxjs/Observer' ;
2
4
import { ReplaySubject } from 'rxjs/ReplaySubject' ;
3
- import { FirebaseRef , FirebaseAuthConfig } from '../tokens' ;
5
+
6
+ import 'rxjs/add/operator/mergeMap' ;
7
+ import 'rxjs/add/operator/take' ;
8
+ import 'rxjs/add/operator/concat' ;
9
+ import 'rxjs/add/operator/skip' ;
10
+ import 'rxjs/add/observable/of' ;
11
+
12
+ import { FirebaseApp , FirebaseAuthConfig } from '../tokens' ;
4
13
import { isPresent } from '../utils/utils' ;
5
14
import * as utils from '../utils/utils' ;
6
15
import {
16
+ authDataToAuthState ,
7
17
AuthBackend ,
8
18
AuthProviders ,
9
19
AuthMethods ,
10
- OAuthCredentials ,
11
- OAuth1Credentials ,
12
- OAuth2Credentials ,
13
- AuthCredentials ,
14
- FirebaseAuthState ,
20
+ EmailPasswordCredentials ,
21
+ OAuthCredential ,
15
22
AuthConfiguration ,
16
- FirebaseAuthDataAllProviders ,
17
- authDataToAuthState
23
+ FirebaseAuthState ,
24
+ stripProviderId
18
25
} from './auth_backend' ;
19
26
20
27
const kBufferSize = 1 ;
@@ -26,20 +33,39 @@ export const firebaseAuthConfig = (config: AuthConfiguration): Provider => {
26
33
} ;
27
34
28
35
@Injectable ( )
29
- export class FirebaseAuth extends ReplaySubject < FirebaseAuthState > {
36
+ export class AngularFireAuth extends ReplaySubject < FirebaseAuthState > {
37
+ private _credentialCache : { [ key :string ] : OAuthCredential } = { } ;
30
38
constructor ( private _authBackend : AuthBackend ,
31
39
@Optional ( ) @Inject ( FirebaseAuthConfig ) private _config ?: AuthConfiguration ) {
32
40
super ( kBufferSize ) ;
33
41
34
- this . _authBackend . onAuth ( ( authData ) => this . _emitAuthData ( authData ) ) ;
42
+ let firstPass = true ;
43
+ this . _authBackend . onAuth ( )
44
+ . mergeMap ( ( authState : FirebaseAuthState ) => {
45
+ // TODO: get rid of side effect
46
+ if ( firstPass ) {
47
+ firstPass = false ;
48
+ return this . _authBackend . getRedirectResult ( )
49
+ . map ( ( userCredential : firebase . auth . UserCredential ) => {
50
+ if ( userCredential && userCredential . credential ) {
51
+ authState = attachCredentialToAuthState ( authState , userCredential . credential , userCredential . credential . provider ) ;
52
+ this . _credentialCache [ userCredential . credential . provider ] = < OAuthCredential > userCredential . credential ;
53
+ }
54
+ return authState ;
55
+ } )
56
+ }
57
+ return Observable . of ( authState ) ;
58
+ } )
59
+ . subscribe ( ( authData : FirebaseAuthState ) => this . _emitAuthData ( authData ) ) ;
35
60
}
36
61
37
- public login ( config ?: AuthConfiguration ) : Promise < FirebaseAuthState > ;
38
- public login ( credentials ?: FirebaseCredentials ) : Promise < FirebaseAuthState > ;
39
- public login ( credentials : AuthCredentials , config ?: AuthConfiguration ) : Promise < FirebaseAuthState > ;
40
- public login ( obj1 ?: any , obj2 ?: AuthConfiguration ) : Promise < FirebaseAuthState > {
62
+ public login ( config ?: AuthConfiguration ) : firebase . Promise < FirebaseAuthState > ;
63
+ // If logging in with email and password
64
+ public login ( credentials ?: EmailPasswordCredentials | firebase . auth . AuthCredential | string ) : firebase . Promise < FirebaseAuthState > ;
65
+ public login ( credentials : EmailPasswordCredentials | firebase . auth . AuthCredential | string , config ?: AuthConfiguration ) : firebase . Promise < FirebaseAuthState > ;
66
+ public login ( obj1 ?: any , obj2 ?: AuthConfiguration ) : firebase . Promise < FirebaseAuthState > {
41
67
let config : AuthConfiguration = null ;
42
- let credentials : AuthCredentials = null ;
68
+ let credentials : EmailPasswordCredentials | firebase . auth . AuthCredential | string = null ;
43
69
if ( arguments . length > 2 ) {
44
70
return this . _reject ( 'Login only accepts a maximum of two arguments.' ) ;
45
71
} else if ( arguments . length == 2 ) {
@@ -74,33 +100,37 @@ export class FirebaseAuth extends ReplaySubject<FirebaseAuthState> {
74
100
75
101
switch ( config . method ) {
76
102
case AuthMethods . Popup :
77
- return this . _authBackend . authWithOAuthPopup ( config . provider , this . _scrubConfig ( config ) ) ;
103
+ return this . _authBackend . authWithOAuthPopup ( config . provider , this . _scrubConfig ( config ) )
104
+ . then ( ( userCredential : firebase . auth . UserCredential ) => {
105
+ // Incorrect type information
106
+ this . _credentialCache [ userCredential . credential . provider ] = < OAuthCredential > userCredential . credential ;
107
+ return authDataToAuthState ( userCredential . user , < OAuthCredential > ( < any > userCredential ) . credential ) ;
108
+ } ) ;
78
109
case AuthMethods . Redirect :
79
- return this . _authBackend . authWithOAuthRedirect ( config . provider , this . _scrubConfig ( config ) ) ;
110
+ // Gets around typings issue since this method doesn't resolve with a user.
111
+ // The method really only does anything with an error, since it redirects.
112
+ return < Promise < FirebaseAuthState > > ( < any > this . _authBackend ) . authWithOAuthRedirect ( config . provider , this . _scrubConfig ( config ) ) ;
80
113
case AuthMethods . Anonymous :
81
114
return this . _authBackend . authAnonymously ( this . _scrubConfig ( config ) ) ;
82
115
case AuthMethods . Password :
83
- return this . _authBackend . authWithPassword ( < FirebaseCredentials > credentials , this . _scrubConfig ( config , false ) ) ;
116
+ return this . _authBackend . authWithPassword ( < EmailPasswordCredentials > credentials ) ;
84
117
case AuthMethods . OAuthToken :
85
- return this . _authBackend . authWithOAuthToken ( config . provider , < OAuthCredentials > credentials ,
118
+ return this . _authBackend . authWithOAuthToken ( < firebase . auth . AuthCredential > credentials ,
86
119
this . _scrubConfig ( config ) ) ;
87
120
case AuthMethods . CustomToken :
88
- return this . _authBackend . authWithCustomToken ( ( < OAuth2Credentials > credentials ) . token ,
89
- this . _scrubConfig ( config , false ) ) ;
121
+ return this . _authBackend . authWithCustomToken ( < string > credentials ) ;
90
122
}
91
123
}
92
124
93
125
public logout ( ) : void {
94
- if ( this . _authBackend . getAuth ( ) !== null ) {
95
- this . _authBackend . unauth ( ) ;
96
- }
126
+ this . _authBackend . unauth ( ) ;
97
127
}
98
128
99
- public getAuth ( ) : FirebaseAuthData {
100
- return this . _authBackend . getAuth ( ) ;
129
+ public getAuth ( ) : FirebaseAuthState {
130
+ return this . _authBackend . getAuth ( )
101
131
}
102
132
103
- public createUser ( credentials : FirebaseCredentials ) : Promise < FirebaseAuthData > {
133
+ public createUser ( credentials : EmailPasswordCredentials ) : firebase . Promise < FirebaseAuthState > {
104
134
return this . _authBackend . createUser ( credentials ) ;
105
135
}
106
136
@@ -115,10 +145,10 @@ export class FirebaseAuth extends ReplaySubject<FirebaseAuthState> {
115
145
return Object . assign ( { } , this . _config , config ) ;
116
146
}
117
147
118
- private _reject ( msg : string ) : Promise < FirebaseAuthState > {
119
- return new Promise ( ( res , rej ) => {
148
+ private _reject ( msg : string ) : firebase . Promise < FirebaseAuthState > {
149
+ return ( < Promise < FirebaseAuthState > > new Promise ( ( res , rej ) => {
120
150
return rej ( msg ) ;
121
- } ) ;
151
+ } ) ) ;
122
152
}
123
153
124
154
private _scrubConfig ( config : AuthConfiguration , scrubProvider = true ) : any {
@@ -131,11 +161,26 @@ export class FirebaseAuth extends ReplaySubject<FirebaseAuthState> {
131
161
}
132
162
133
163
134
- private _emitAuthData ( authData : FirebaseAuthDataAllProviders ) : void {
164
+ private _emitAuthData ( authData : FirebaseAuthState ) : void {
135
165
if ( authData == null ) {
136
166
this . next ( null ) ;
137
167
} else {
138
- this . next ( authDataToAuthState ( authData ) ) ;
168
+ if ( authData . auth && authData . auth . providerData && authData . auth . providerData [ 0 ] ) {
169
+ let providerId = authData . auth . providerData [ 0 ] . providerId ;
170
+ let providerCredential = this . _credentialCache [ providerId ] ;
171
+ if ( providerCredential ) {
172
+ authData = attachCredentialToAuthState ( authData , providerCredential , providerId ) ;
173
+ }
174
+ }
175
+
176
+ this . next ( authData ) ;
139
177
}
140
178
}
141
179
}
180
+
181
+ function attachCredentialToAuthState ( authState : FirebaseAuthState , credential , providerId : string ) : FirebaseAuthState {
182
+ if ( ! authState ) return authState ;
183
+ // TODO make authState immutable
184
+ authState [ stripProviderId ( providerId ) ] = credential ;
185
+ return authState ;
186
+ }
0 commit comments