Authentication

Login Objects

Session:


Catalog objects:


Status:


Login Flow: 

In the login window /sign-in  (SignInComponent) the method of authentication is chosen. For the providers, Google, Facebook and Github, the corresponding 'provider' is given and through the AuthService.AuthLogin method is called

AuthService.AuthLogin:

 This clears the session variables and then using the AngularFireAuth service, the  signup window is setup and the result observable, meaning the authentification user information is given.  With this user, the AuthService.SetUserData is called:


AuthService.getUserInformationFromServer

This method is called when not all the user account information has been set up. It will use the status to determine what will be done.

This method calls the service /login (LoginService) with essentually the authentification user information and the token. If the call fails, then the session will be cleared and nothing happens.

If the session succeeds the status is retrieved and set in the session.

If the status is dataset:LoginAuthenticated, this means that this is the very first call and the dataset:LoginAccountInformation catalog object is created.



Implementation


Angular UI

https://www.positronx.io/full-angular-7-firebase-authentication-system/

or maybe this one:

https://github.com/AnthonyNahas/ngx-auth-firebaseui


Notes on Authentication:

https://github.com/angular/angularfire/blob/master/docs/auth/getting-started.md


This is the general pattern.

The result of the authenticationn is 


The User information:

SetUserData(user) {

    const userRef: AngularFirestoreDocument<any> = this.afs.doc(`users/${user.uid}`);

    const userData: User = {

      uid: user.uid,

      email: user.email,

      displayName: user.displayName,

      photoURL: user.photoURL,

      emailVerified: user.emailVerified

    }

    return userRef.set(userData, {

      merge: true

    })

  }


A token is generated with the 


Manage Users:

https://firebase.google.com/docs/auth/admin/manage-users#java

Retrieve User data for the backend:

UserRecord userRecord = FirebaseAuth.getInstance().getUser(uid);

// See the UserRecord reference doc for the contents of userRecord.

System.out.println("Successfully fetched user data: " + userRecord.getUid());

or

UserRecord userRecord = FirebaseAuth.getInstance().getUserByEmail(email);

// See the UserRecord reference doc for the contents of userRecord.

System.out.println("Successfully fetched user data: " + userRecord.getEmail());

Create a user:

CreateRequest request = new CreateRequest()

    .setEmail("user@example.com")

    .setEmailVerified(false)

    .setPassword("secretPassword")

    .setPhoneNumber("+11234567890")

    .setDisplayName("John Doe")

    .setPhotoUrl("http://www.example.com/12345678/photo.png")

    .setDisabled(false);


UserRecord userRecord = FirebaseAuth.getInstance().createUser(request);

System.out.println("Successfully created new user: " + userRecord.getUid());


API_KEY: 

The API_KEY for blurock-database is AIzaSyDru7mwaZdl1kh8EVAr2QwkWK2gTaJnFUk 


TokenIDs

https://firebase.google.com/docs/database/rest/auth#firebase_id_tokens

Verify ID tokens using the Firebase Admin SDK

https://firebase.google.com/docs/auth/admin/verify-id-tokens#verify_id_tokens_using_the_firebase_admin_sdk


// idToken comes from the client app (shown above)

FirebaseToken decodedToken = FirebaseAuth.getInstance().verifyIdToken(idToken);

String uid = decodedToken.getUid();

https://firebase.google.com/docs/auth/admin/verify-id-tokens#retrieve_id_tokens_on_clients

When a user or device successfully signs in, Firebase creates a corresponding ID token that uniquely identifies them and grants them access to several resources, such as Firebase Realtime Database and Cloud Storage. You can re-use that ID token to identify the user or device on your custom backend server. To retrieve the ID token from the client, make sure the user is signed in and then get the ID token from the signed-in user:

firebase.auth().currentUser.getIdToken(/* forceRefresh */ true).then(function(idToken) {

  // Send token to your backend via HTTPS

  // ...

}).catch(function(error) {

  // Handle error

});


Get TokenID in Angular:

The fix for your code is to return a Promise, instead of trying to return the value:

GetToken(): Promise<string> {

  return new Promise((resolve, reject) => {

    this.afAuth.auth.onAuthStateChanged( user => {

      if (user) {

        user.getIdToken().then(idToken => {

          this.userToken = idToken;

          resolve(idToken);    

        });

      }

    });

  })

}


In words: GetToken returns a promise that resolves once an ID token is available. If you know the user is already signed in when you call this function, you can simplify it to:

GetToken(): string {

    const user = firebase.authentication().currentUser;

    return user.getIdToken()

}


The difference is that the second function does not wait for the user to be signed in, so will fail if there is no signed in user.

Asynchronous

For more on this see How to return value from an asynchronous callback function? I highly recommend studying this answer for a while, as this asynchronous behavior is incredibly common when dealing with web APIs.

https://www.nerd.vision/post/using-firebase-auth-in-angular-components-synchronously

Send TokenID from client to Server

https://stackoverflow.com/questions/47775444/how-to-authenticate-user-on-server-with-firebase-when-they-are-already-authentic

Sending a request from Angular:

postRequest() {

    const url = 'https://your-endpoint';

    firebase.auth().currentUser.getIdToken()

            .then(authToken => {

              const headers = new Headers({'Authorization': 'Bearer ' + authToken });

              return this.http.post(url, { someData } , { headers }).toPromise()

            })

    }


This is the code on the backend, in Node.js.... to be translated to JAVA

const admin = require('firebase-admin');

admin.initializeApp(yourConfig);

const express = require('express')

const app = express()


app.post('/your-endpoint', (req, res) => {


  const token = req.headers.authorization.split('Bearer ')[1]


  return admin.auth().verifyIdToken(token)

              .then(decodedToken => {

                  const uid = decodedToken.uid;

                  res.status(200).send('Looks good!')


              })

              .catch(err => res.status(403).send('Unauthorized'))



});


http://www.avajava.com/tutorials/lessons/how-do-i-use-basic-authentication-with-tomcat.html

package test;


import java.io.IOException;

import java.io.PrintWriter;

import java.util.Enumeration;


import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


import org.apache.tomcat.util.buf.Base64;


public class TestServlet extends HttpServlet {


private static final long serialVersionUID = 1L;


protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

out.println("This is the Test Servlet");


Enumeration headerNames = request.getHeaderNames();

while (headerNames.hasMoreElements()) {

String headerName = (String) headerNames.nextElement();

out.print("<br/>Header Name: <em>" + headerName);

String headerValue = request.getHeader(headerName);

out.print("</em>, Header Value: <em>" + headerValue);

out.println("</em>");

}

out.println("<hr/>");

String authHeader = request.getHeader("authorization");

String encodedValue = authHeader.split(" ")[1];

out.println("Base64-encoded Authorization Value: <em>" + encodedValue);

String decodedValue = Base64.base64Decode(encodedValue);

out.println("</em><br/>Base64-decoded Authorization Value: <em>" + decodedValue);

out.println("</em>");

}


}


Critical code:

String authHeader = request.getHeader("authorization");

String encodedValue = authHeader.split(" ")[1];

out.println("Base64-encoded Authorization Value: <em>" + encodedValue);

String decodedValue = Base64.base64Decode(encodedValue);

out.println("</em><br/>Base64-decoded Authorization Value: <em>" + decodedValue);

out.println("</em>");


Backend

Maven

<dependency>

  <groupId>com.google.firebase</groupId>

  <artifactId>firebase-admin</artifactId>

  <version>8.1.0</version>

</dependency>


These are the docs to  Add Firebase to Backend.

FirebaseOptions options = FirebaseOptions.builder()

    .setCredentials(GoogleCredentials.getApplicationDefault())

    .setProjectId("<FIREBASE_PROJECT_ID>")

    .build();


FirebaseApp.initializeApp(options);



When calling backend

httpOptions = {

    headers: new HttpHeaders({

      'Content-Type': 'application/json',

      'Authorization': 'JWT ' + 'ey.....'

    }),

  };