@@ -38,81 +38,105 @@ const basicAuthRequest = require('request');
38
38
* Authenticate the provided credentials returning a Firebase custom auth token.
39
39
* `username` and `password` values are expected in the body of the request.
40
40
* If authentication fails return a 401 response.
41
+ * If the request is badly formed return a 400 response.
42
+ * If the request method is unsupported (not POST) return a 403 response.
41
43
* If an error occurs log the details and return a 500 response.
42
44
*/
43
45
exports . auth = functions . https . onRequest ( ( req , res ) => {
46
+
47
+ const handleError = ( username , error ) => {
48
+ console . error ( {
49
+ User : username
50
+ } , error ) ;
51
+ return res . sendStatus ( 500 ) ;
52
+ }
53
+
54
+ const handleResponse = ( username , status , body ) => {
55
+ console . log ( {
56
+ User : username
57
+ } , {
58
+ Response : {
59
+ Status : status ,
60
+ Body : body
61
+ }
62
+ } ) ;
63
+ if ( body ) {
64
+ return res . status ( 200 ) . json ( body ) ;
65
+ }
66
+ return res . sendStatus ( status ) ;
67
+ }
68
+
69
+
70
+ let username = '' ;
44
71
try {
45
72
cors ( req , res , ( ) => {
46
73
// Authentication requests are POSTed, other requests are forbidden
47
74
if ( req . method !== 'POST' ) {
48
- return res . sendStatus ( 403 ) ;
75
+ return handleResponse ( username , 403 ) ;
49
76
}
50
- let username = req . body . username ;
77
+ username = req . body . username ;
51
78
if ( ! username ) {
52
- return res . sendStatus ( 400 ) ;
79
+ return handleResponse ( username , 400 ) ;
53
80
}
54
- let password = req . body . password ;
81
+ const password = req . body . password ;
55
82
if ( ! password ) {
56
- return res . sendStatus ( 400 ) ;
83
+ return handleResponse ( username , 400 ) ;
57
84
}
58
85
59
- let creds = {
60
- 'auth' : {
61
- 'user' : username ,
62
- 'pass' : password
86
+ // TODO(DEVELOPER): In production you'll need to update the `authenticate` function so that it authenticates with your own credentials system.
87
+ authenticate ( username , password ) . then ( valid => {
88
+ if ( ! valid ) {
89
+ return handleResponse ( username , 401 ) ; // Invalid username/ password
63
90
}
64
- }
65
-
66
- // For the purpose of this example use httpbin (https://httpbin.org) for the basic authentication request.
67
- // (Only a password of `Testing123` will succeed)
68
- const authEndpoint = `https://httpbin.org/basic-auth/${ username } /Testing123` ;
69
91
70
- basicAuthRequest ( authEndpoint , creds , ( error , response , body ) => {
71
- let statusCode = response ? response . statusCode : 0 ;
72
- if ( statusCode === 401 ) { // Invalid username/password
73
- return res . sendStatus ( 401 ) ;
74
- }
75
- if ( statusCode !== 200 ) {
76
- console . log ( 'ERROR: invalid response returned from ' , authEndpoint , ' status code ' , statusCode ) ;
77
- return res . sendStatus ( 500 ) ;
78
- }
79
- // On success create/update the Firebase account and return the Custom Auth Token.
80
- // - any extra user details can also be created/updated here
81
- createFirebaseAccount ( username ) . then ( firebaseToken => {
82
- return res . status ( 200 ) . json ( {
92
+ // On success return the Firebase Custom Auth Token.
93
+ admin . auth ( ) . createCustomToken ( username ) . then ( firebaseToken => {
94
+ return handleResponse ( username , 200 , {
83
95
token : firebaseToken
84
96
} ) ;
97
+ } ) . catch ( error => {
98
+ return handleError ( username , error ) ;
85
99
} ) ;
100
+
101
+ } ) . catch ( error => {
102
+ return handleError ( username , error ) ;
86
103
} ) ;
87
104
} ) ;
88
105
} catch ( error ) {
89
- console . log ( 'ERROR:' , error ) ;
90
- return res . sendStatus ( 500 ) ;
106
+ return handleError ( username , error ) ;
91
107
}
92
108
} ) ;
93
109
94
110
/**
95
- * Creates a Firebase account with the given user id and returns a custom auth token allowing
96
- * signing-in this account.
97
- *
98
- * @returns {Promise<string> } The Firebase custom auth token in a promise.
111
+ * Authenticate the provided credentials.
112
+ * TODO(DEVELOPER): In production you'll need to update this function so that it authenticates with your own credentials system.
113
+ * @returns {Promise<boolean> } success or failure.
99
114
*/
100
- function createFirebaseAccount ( uid ) {
101
- // Create or update the user account.
102
- const userCreationTask = admin . auth ( ) . updateUser ( uid , { } ) . catch ( error => {
103
- // If user does not exists we create it.
104
- if ( error . code === 'auth/user-not-found' ) {
105
- return admin . auth ( ) . createUser ( {
106
- uid : uid
107
- } ) ;
115
+ function authenticate ( username , password ) {
116
+
117
+ // For the purpose of this example use httpbin (https://httpbin.org) and send a basic authentication request.
118
+ // (Only a password of `Testing123` will succeed)
119
+ const authEndpoint = `https://httpbin.org/basic-auth/${ username } /Testing123` ;
120
+ const creds = {
121
+ 'auth' : {
122
+ 'user' : username ,
123
+ 'pass' : password
108
124
}
109
- throw error ;
110
- } ) ;
111
- // Wait for all async task to complete then generate and return a custom auth token.
112
- return Promise . all ( [ userCreationTask ] ) . then ( ( ) => {
113
- // Create a Firebase custom auth token.
114
- const token = admin . auth ( ) . createCustomToken ( uid ) ;
115
- console . log ( 'Created Custom token for UID "' , uid , '" Token:' , token ) ;
116
- return token ;
125
+ }
126
+ return new Promise ( ( resolve , reject ) => {
127
+ basicAuthRequest ( authEndpoint , creds , ( error , response , body ) => {
128
+ if ( error ) {
129
+ return reject ( error )
130
+ }
131
+ const statusCode = response ? response . statusCode : 0 ;
132
+ if ( statusCode === 401 ) { // Invalid username/password
133
+ return resolve ( false ) ;
134
+ }
135
+ if ( statusCode !== 200 ) {
136
+ return reject ( Error ( 'invalid response returned from ' , authEndpoint , ' status code ' , statusCode ) ) ;
137
+ }
138
+ return resolve ( true ) ;
139
+ } ) ;
117
140
} ) ;
141
+
118
142
}
0 commit comments