Login med JWT

By . Latest revision .

Vi har i tidigare kurser och i andra programmeringsspråk hanterat inloggning med hjälp av sessioner. I denna övning ska vi titta på ett sätt att autentisera våra klienter mot servern utan sessioner. Detta ger oss vissa fördelar som att vi har inbyggda utlöpstider och att det underlättar om vi vill skala upp vårt API, samtidigt som det ger ett säkert sätt att identifiera klienterna på.

I denna övning tittar vi på hur vi med hjälp av Postman registrerar en användare, loggar in som denna användare och får en JSON Web Token (JWT). Sist i övningen tittar vi på hur vi med hjälp av JWT kommer åt funktioner i Lager API:t som ligger skyddade.

#Registrering och inloggning

Vi börjar med att registrera en användare i Lager API:t genom att skicka en POST till URL’en /v2/auth/register med 3 parametrar i body: api_key, email och password. Detta kan till exempel göras med Postman eller som en POST request från JavaScript.

Vi får följande svar från Lager API:t:

{
    "data": {
        "message": "User successfully registered."
    }
}

När vi sedan vill logga in som den nyss registrerade användaren gör vi det genom att skicka en POST till URL’en /v2/auth/login med de samma 3 parametrar i body: api_key, email och password.

Vi får följande svar från Lager API:t. token i det nedanstående data objektet är den JSON web token vi har fått tillbaka från API:t.

{
    "data": {
        "type": "success",
        "message": "User logged in",
        "user": {
            "api_key": "...",
            "email": "new@example.com"
        },
        "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhc...NzczfQ.zUUd...KHTkM"
    }
}

#Använda JSON Web Tokens

Vi ser att svaret från Lager API:t innehåller attributet token och detta är vår JWT som vi använder varje gång vi vill åt funktioner i API:t som ligger bakom skyddet. Vi skickar med token som x-access-token i HTTP-headern.

I fetch kan du skicka med headers på följande sätt.

const response = await fetch("https://lager.emilfolino.se/v2/invoices?api_key=[YOUR_API_KEY]", {
    headers: {
      'x-access-token': [TOKEN]
    },
});
const result = await response.json();

#Exempelprogram

Jag har valt att skapa en modell models/auth.js som får hålla koll på om vi har en token eller ej. I modellen finns även de funktioner som står för logga in och registreing med hjälp av fetch till Lager-API:t.

import { apiKey, baseURL } from "../utils.js";

const auth = {
    token: "",

    login: async function login (username, password) {
        const user = {
            email: username,
            password: password,
            api_key: apiKey
        };

        const response = await fetch(`${baseURL}/auth/login`, {
            body: JSON.stringify(user),
            headers: {
              'content-type': 'application/json'
            },
            method: 'POST'
        });

        const result = await response.json();

        if (result.data.type === "success") {
            auth.token = result.data.token;
            console.log(auth.token);
            return "ok";
        }

        return "not ok";
    },

    register: async function register (username, password) {
        const user = {
            email: username,
            password: password,
            api_key: apiKey
        };

        const response = await fetch(`${baseURL}/auth/register`, {
            body: JSON.stringify(user),
            headers: {
              'content-type': 'application/json'
            },
            method: 'POST'
        });

        const result = await response.json();

        if (result.data.message === "User successfully registered.") {
            return "ok";
        }

        return "not ok";
    },
};

export default auth;

Vi kan sedan i våra komponenter och vyer använda detta för att ge användare tillgång till de olika delar som i vanliga fall ligger bakom lås och bom.

Till exempel kan det se ut på följande sätt i faktura-vyn views/invoices.js där vi först kollar om användaren är inloggat annars ändrar vi location.hash för att istället visa login-vyn.

import authModel from "../models/auth.js";

export default class InvoicesView extends HTMLElement {
    // connect component
    connectedCallback() {
        if (!authModel.token) {
            location.hash = "login";
        }

        this.render();
    }

    render() {
        this.innerHTML =    `<header class="header">
                                <lager-title title="Fakturor"></lager-title>
                             </header>
                             <main class="main">
                                <invoices-table></invoices-table>
                             </main>
                             `;
    }
}

#Avslutningsvis

Vi har i denna artikel använd oss av Postman för att registrera en användare och logga in med den användaren. Vi har även tittat på hur man kan använda headers som en del av ett anrop med fetch.

#Revision history

  • 2018-02-07: (A, efo) Första utgåvan inför kursen webapp v3.

Document source.

Category: javascript.