Categories
JavaScript Nodejs

How to Add Twitter Sign In to Your Node.js Back End

Twitter uses the standard OAuth for authentication, which means you incorporate a standardized way of logging in if you use Twitter sign in.

In Node.js, it is very easy to add Twitter sign in to an Express web app.


Getting Started

First, you have to make an Express app. Express is a routing library with a lot of add-ons built for easy web development.

There are many Express app boilerplates available on the web. There is also an Express code generator from the makers of the Express framework.

Using the latest Node.js versions, you can run npx express-generator.

If npx is not available, you can install express-generator globally and run that:

$ npm install -g express-generator  
$ express

Make a folder for your project and follow the instructions.

To make the example simple, this app will provide the redirect URL that you get after providing the consumer key and request token for the Angular app.

Then, after the user goes through the Twitter sign in, it will redirect back to the Angular app, which will then call the Express API to save the OAuth access token and the OAuth access token secret to a database.

We need to make an entry point file for Express.

We need to install express-session, express-logger, cookie-parser, and cors for saving sessions, logging, parsing cookies, and allowing external requests for our Angular app, respectively.

babel-register and bale-polyfill are required to use the latest JavaScript features in our Node.js web app.

To save the secrets, use the [dotenv](https://www.npmjs.com/package/dotenv) library. With this, the secrets will be read from the .env file, rather than hard coding them into the code, which is very bad secret practice.

To get the Twitter keys, you have to apply for a developer account at https://developer.twitter.com/. You will then get the keys and secrets required, which you will put into the .env file.

The .env file should be a key-value list, like this:

TWITTER_CONSUMER_KEY=''  
TWITTER_CONSUMER_SECRET=''  
TWITTER_CALLBACK_URL='http://localhost:4200/settings'
SESSION_SECRET=''

I will call the entry point file app.js .

To run this, go to your project folder and run node app.js:

Then, we need the oauth library to make an oauth.OAuth object which will allow the Express app to get the request token and request token secret.

Add a controllers folder in the same level as app.js.

Then, add sessionsController.js into the controllers folder.

Add the following to sessionsController.js:

The connect route will send the Twitter sign-in URL as the redirect URL.

Then, the Angular app will call the saveAccessTokens route to store the OAuth access token and its secret in the session.


Angular CLI

To build the Angular app, you need the Angular CLI.

To install it, run npm i -g @angular/cli in your Node.js command prompt. Then, run ng new frontend to generate the skeleton code for your front end app.

Also, install @angular/material according to the Angular documentation.

After that, replace the default app.module.ts with the following:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import {
  MatButtonModule,
  MatTableModule,
  MAT_DIALOG_DEFAULT_OPTIONS,
} from '@angular/material';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { SettingsPageComponent } from './settings-page/settings-page.component';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { SessionService } from './session.service';
import { HttpReqInterceptor } from './http-req-interceptor';
@NgModule({
  declarations: [
    AppComponent,
    SettingsPageComponent,
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule,
    MatButtonModule,
    FormsModule,
    HttpClientModule,
  ],
  providers: [
    SessionService,
    {
      provide: HTTP_INTERCEPTORS,
      useClass: HttpReqInterceptor,
      multi: true
    },
    UserService,
    TweetsService,
  ],
  bootstrap: [AppComponent],
})
export class AppModule { }

We need to use Angular’s HTTP client to connect to our Express routes to get the redirect URL and get the access token from the redirect after logging in with Twitter, then send it back to our route.

To do this, run ng g service session.

This will create session.service.ts:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { environment } from 'src/environments/environment';
@Injectable({
  providedIn: 'root'
})
export class SessionService {
  constructor(private http: HttpClient) { }
  getRedirectUrl() {
  return this.http.get(`${environment.apiUrl}/sessions/connect`)
}
  saveAccessToken(oauthToken: string, oauthVerifier: string) {
    return this.http.get(`${environment.apiUrl}/sessions/saveAccessTokens?oauth_token=${oauthToken}&oauth_verifier=${oauthVerifier}`)
  }
}

In here, environment.apiUrl is the URL to our API, which is specified in environment.ts.

Now, we need a page with a button that calls our Express route to get the redirect URL.

Run ng g component settingsPage to create settings-page.component.ts and settings-page.component.html, which is where the button will be placed.

Add the following to settings-page.component.html:

<div>  
  <button mat-raised-button (click)='redirectToTwitter()'>Connect to Twitter Account</button>  
</div>

Then, add the following settings-page.component.ts:

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { SessionService } from '../session.service';
@Component({
  selector: 'app-settings-page',
  templateUrl: './settings-page.component.html',
  styleUrls: ['./settings-page.component.scss']
})
export class SettingsPageComponent implements OnInit {
  constructor(
    private activatedRoute: ActivatedRoute,
    private sessionService: SessionService,
  ) {
    this.activatedRoute.queryParams.subscribe(params => {
      const oauthVerifier = params['oauth_verifier'];
      const oauthToken = params['oauth_token'];
      if (oauthToken && oauthVerifier) {
        this.saveAccessToken(oauthToken, oauthVerifier);
      }
    });
  }
  ngOnInit() {}
  saveAccessToken(oauthToken: string, oauthVerifier: string) {
    this.sessionService.saveAccessToken(oauthToken, oauthVerifier).subscribe(res => {
    alert('Token saved');
    })
  }
  redirectToTwitter() {
    this.sessionService.getRedirectUrl().subscribe((res: any) => {
      location.href = res.redirectUrl;
    })
  }
}

After adding the code above, you get a button that, after you click it, will go to the Twitter sign-in page.

Then, once Twitter sign in succeeds, you will be redirected to the same page with the OAuth access token and verifier, which will be sent to our Express API and stored in the session.


Token Saved

You will get Token saved message once it succeeds.

In the end, this is the workflow you should get:

  1. First, you get the connect button:

https://thewebdev.info/wp-content/uploads/2020/05/connect.png

  1. Then, you are redirected to the Twitter login:

https://thewebdev.info/wp-content/uploads/2020/05/twitter-login.png

  1. Finally, you are redirected back with the OAuth access token and verifier, and with those, you get the access token and secret which will be stored to the session.

If that succeeds, the saveAccessTokens route will return a successful response, which will then trigger the Angular app to alert Token saved.

Categories
JavaScript TypeScript

Introduction to TypeScript Classes — Static Properties, Abstract Classes and More

Classes in TypeScript, as in JavaScript, are a special syntax for its prototypical inheritance model that’s a comparable inheritance in class-based object oriented languages. Classes are just special functions added to ES6 that are meant to mimic the class keyword from these other languages.

In JavaScript, we can have class declarations and class expressions because they’re just functions. So like all other functions, there are function declarations and function expressions. This is the same with TypeScript. Classes serve as templates to create new objects. TypeScript extends the syntax of classes of JavaScript and then adds its own twist to it. In this piece, we’ll look at static properties, abstract classes, and constructor functions.


Static Properties

With TypeScript, we can designate members as instance variables, which don’t have the keyword static before them, and static members, which have the keyword static keyword before them.

Static members can be accessed without having the class instantiated. Of course, this is given to the access modifiers that are designated for the member. So public static members can be accessed directly from outside the class. Private static members can only be used within the class, and protected members can be accessed by a class the member is defined in and also by subclasses of that class.

The static keyword can be used by both fields and methods. For example, we can use it like in the following code:

class Person {  
  static numPeople = 0;    
  constructor(name: string) {  
    Person.numPeople++;  
  }  
  static getNumPeople() {  
    return this.numPeople;  
  }  
}

const john = new Person('John');  
const jane = new Person('Jane');  
console.log(Person.numPeople);  
console.log(Person.getNumPeople());

In the code above, every time we instantiate the Person class, we increase the static property numPeople by one. Since static properties are shared by all instances of the class and don’t belong to any one instance, we can access numPeople directly by using Person.numPeople.

Likewise, we have a static method, getNumPeople, we can call directly without instantiating the Person class. Therefore, when we get the numPeople by using Person.numPeople and call the Person.getNumPeople(), then the value 2 is returned for both.

Since the members are static, the values is part of a class and not part of any instance, so even if the instances are destroyed the values will be kept. This is different from instance variables, which are accessed from the this inside the class and the variable with the instance of the class outside the class.


Abstract Classes

TypeScript has abstract classes, which are classes that have partial implementation of a class and in which other classes can be derived from. They can’t be instantiated directly.

Unlike interfaces, abstract classes can have implementation details for their members. To declare an abstract class, we can use the abstract keyword. We can also use the abstract keyword for methods to declare abstract methods, which are implemented by classes that derive from an abstract class.

Abstract methods don’t contain implementations of the method. It’s up to the subclasses that derive from the abstract class to implement the method listed. They may also, optionally, include access modifiers.

We can use abstract classes and methods as demonstrated in the following code:

abstract class Person {  
  name: string;  
  age: number;  
  constructor(name: string, age: number) {  
    this.name = name;  
    this.age = age;  
  } abstract getName(): string;  
  abstract getAge(): number;  
}

class Employee extends Person{  
  constructor(name: string, age: number) {  
    super(name, age);  
  } 

  getName() {  
    return this.name;  
  } 

  getAge() {  
    return this.age;  
  }  
}

let employee = new Employee('Jane', 20);  
console.log(employee.getName());  
console.log(employee.getAge());

In the code above, we have the abstract Person class, which has the abstract methods getName and getAge.

As we can see, the abstract methods only have signatures in them. The actual implementation of the methods are in the Employee class, which extends the Person class.

We have the actual implementation of the getName and getAge methods in the Employee class.

TypeScript checks the method signature and the return type of the class, so we must be implementing the abstract methods as it’s outlined in the abstract class. This means that in the example above, the getName method must take no parameters and must return a string.

Likewise, the getAge method must take no parameters and must return a number. After the abstract methods have been implemented, we can call them normally like any other method.


Constructor Functions

When we declare a TypeScript, we’re declaring multiple things at the same time. We’re declaring an instance of the class, which is the entity with the code preceded with the class keyword. For example, we can write:

class Employee{  
  name: string;  
  age: number;  
  constructor(name: string, age: number) {  
    this.name = name;  
    this.age = age;  
  }
}  
let employee: Employee = new Employee('Jane', 20);

In the last line of the code snippet above, we’re using Employee as the type of the instances of the class Employee.

Also, we’re creating another value we call a constructor function. This is the function that’s called when the new keyword is being used to create a new instance of the class.

If we compile the TypeScript code above to ES5 or earlier, we can see we get something like the following code generated:

"use strict";  
var Employee = /** @class (function () {  
    function Employee(name, age) {  
        this.name = name;  
        this.age = age;  
    }  
    return Employee;  
}());  
var employee = new Employee('Jane', 20);

In the code above, the constructor function is the following code:

function Employee(name, age) {  
  this.name = name;  
  this.age = age;  
}

We have this because in JavaScript, no matter what version we’re using, a class is just the syntactic sugar for constructor functions. The inheritance model of TypeScript just extends from JavaScript. It didn’t change the inheritance model of JavaScript since it’s supposed to be 100% compatible with existing JavaScript code so existing JavaScript code can be adopted to use TypeScript.

In TypeScript, we can get the type of the constructor function with the typeof operator. It’s different from its usage in JavaScript as it has been extended to get the type of the constructor function of a class. If we run the following code …

class Employee{  
  name: string;  
  age: number;  
  static companyName: string = 'ABC Company';  
  constructor(name: string, age: number) {  
    this.name = name;  
    this.age = age;  
  }}

let employeeConstructor: typeof Employee = Employee;  
console.log(Employee.companyName);  
console.log(employeeConstructor.companyName);

… it makes sense when we get the value of the static member companyName logged in both console.log statements. As we can see from the compiled output …

"use strict";  
var Employee = /** @class */ (function () {  
    function Employee(name, age) {  
        this.name = name;  
        this.age = age;  
    }  
    Employee.companyName = 'ABC Company';  
    return Employee;  
}());  
var employeeConstructor = Employee;  
console.log(Employee.companyName);  
console.log(employeeConstructor.companyName);

… a JavaScript and TypeScript class are ultimately just functions. The class syntax makes inheritance of JavaScript easier to use since it looks like it’s using class-based inheritance, but it’s actually syntactic sugar on top of the prototypical inheritance model that’s been the same since JavaScript first came out.

TypeScript makes inheritance easy by letting us define abstract classes — where some implementation is done by the abstract and others are done in the subclass that extends the abstract class.

We also have abstract methods that subclasses can implement. Abstract methods only have the signature and return type and no implementation details.

Static members let us define members that are part of the class rather than an instance of the class.

It’s also important to know that the class syntax is ultimately syntactic sugar for the prototypical inheritance model that existed since the beginning of JavaScript. However, now we can put that aside since we can use the syntactic sugar to make it easier to understand and implement inheritance.