Щракнете тук, за да споделите тази статия в LinkedIn »

Демонстрация на обсъжданите тук принципи може да бъде намеренаhttp://vue-auth0-demo.s3-website.eu-central-1.amazonaws.com. Освен това, за по-голяма яснота, в тази статия са пропуснати някои подробности. Изходният код за по-пълен пример (демото по-горе) може да бъде намерен наhttps://github.com/sellomkantjwa/vue-auth0-demo.

Ако използвате Auth0, за да управлявате потребителите на едностраничното си приложение, бързо ще научите, че е ужасна практика да съхранявате токени за опресняванев браузъра като част от вашето състояние. Това е така, защото токените за опресняване никога не изтичат и ако някой някога бъде компрометиран, тогава нападателят може да използва този единствен токен за опресняване, за да опреснява токените за достъп на своята жертва за неопределено време – това е лошо.

Ако имате приложение, при което потребителят е малко вероятно да бъде онлайн непрекъснато повече от 2 часа (по подразбиране TTL на токен за достъп auth0), тогава може да решите просто да оставите токена да изтече и да помолите потребителя да влезе отново, ако трябва искат да продължат сесията си извън TTL. Аз лично не подкрепям този подход — представете си сценарий, при който потребител влиза в приложението ви, използва го в продължение на 10 минути, превключва на нов раздел, връща се към приложението ви известно време по-късно и започва да клика наоколо. Изведнъж, трясък по средата на сесия, токенът изтича и им се показва екран за вход — не е готино. Нека видим как можем да гарантираме, че това никога няма да се случи.

Най-лесният начин да работите с Auth0 в браузъра е да изтеглите техния SDK.

използвайки npm:

npm i auth0-js -SE 

или включете скрипта на вашата страница:

<script src=”https://cdn.auth0.com/js/auth0/9.3.1/auth0.min.js"></script>

Управлението на сесията на потребителя не е прекалено сложно и може да се обобщи по следния начин:

  1. Когато потребител влезе в нашето приложение за първи път, ние улавяме и съхраняваме:
    * access_token (За правилното използване на Auth0 и Oauth имаме нужда от това, за да се удостоверим на нашия API/сървър)
    * expires_in (което ни казва колко време преди изтичането на токена)
  2. Планираме setTimeout за няколко минути преди изтичането на токена, за да опресним токена.
  3. Когато потребителят качи следващия път на нашето приложение, ние проверяваме дали той е влизал преди това; ако имат, проверяваме дали техният токен е изтекъл или ще изтече скоро и ги изпращаме на страницата за вход, ако това е така. Ако токенът не е изтекъл && не е близо до изтичане, ние просто ги пускаме да влязат и планираме опресняване, когато токенът ще бъде близо до изтичане.

Нека започнем със създаването на помощен модул, който ще използваме за управление на сесията на потребителя. В него ще създадем и експортираме нов екземпляр на auth0, който можем да използваме повторно навсякъде.

//session-manager.js

//Irrelevant code omitted for clarity
 
import {WebAuth} from "auth0-js";

const auth0 = new WebAuth({
    responseType: "token id_token",
    domain: process.env.DEMO_AUTH0_DOMAIN,
    clientID: process.env.DEMO_AUTH0_CLIENT_ID,
    redirectUri: "http://localhost:8080/login-callback"
});
export{auth0}
//irrelevant code omitted

Имайте предвид, че ние съхраняваме нашия домейн и clientID като конфигурируеми променливи. Можете да ги кодирате твърдо, ако искате.

Сега компонентът за влизане.

Ще видите, че всичко, което правим тук, е да извикаме auth0.authorize(), което пренасочва потребителя към нашата страница, хоствана от Auth0, където ще може да влезе. Тази страница изглежда малко по следния начин:

След като потребителят влезе в системата, той ще бъде пренасочен към определения от нас URL адрес, където можем да извлечем и съхраним токена. В настройката по-горе (session-manager.js) посочихме URI http://localhost:8080/login-callback(уверете се, че URL адресът е в списъка с разрешени URL адреси за обратно извикване в Auth0, в противен случай всичко ще се взриви.)

Нека съберем и съхраним токена на потребителя в определения URI за пренасочване.

Когато бъдем пренасочени към http://localhost:8080/login-callback,горният компонент се зарежда. Единствената му цел е да събира, анализира и съхранява върнатите токени. Когато auth0 се върне към URL адреса за обратно извикване, той добавя необходимия токен и изтичане към хешв URL адреса. Целият URL адрес изглежда така:

http://localhost:8080/login-callback#access_token=xxxxxxxxxxxxxxxxxxxxxxxxx&expires_in=7200&token_type=Bearer&state=xxxxxxxxxxxxxxxxx&id_token=xxxxxxxxxxxxxxxxxxxxxxxx

Ние използваме модула querystring, за да анализираме данните за токена в JSON за лесна обработка и след това да ги предадем на Vuex мутация за съхранение в нашето централно състояние. Анализираните данни за токени изглеждат по следния начин:

{
  "access_token":"xxxxxxxxxxxxxxxxx",
  "expires_in":"7200",
  "token_type":"Bearer",
  "state":"xxxxxxxxxxxxxxxxx",
  "id_token":"xxxxxxxxxxxxxx"
}

След това в нашия магазин Vuex можем да запазим нашите токени в нашето централно състояние и localstorage. Трябва да запазим токена в localstorage, за да можем да го запазим при презареждания на страници или последователни посещения на сайта, преди токенът да е изтекъл. По този начин можем да използваме повторно токена, вместо да молим потребителя да влиза всеки път, когато натисне приложението. По-долу е фрагмент от нашия магазин, където дефинираме мутацията, която е отговорна за запазването на токените.

Страхотно, вече съхранихме идентификационните си данни и можем да настроим гетъри, така че да можем да ги извличаме, когато имаме нужда. Ето пълния магазин:

Сега искаме да настроим опреснявания на токени, така че потребителят да не излиза от активна сесия, също така искаме да инициализираме сесията правилно, когато потребителят влезе в приложението. Нека хвърлим цялата тази логика в session-manager.js.

//session-manager.js

Функцията initSession прави следното:

  1. Проверете дали имаме дата на изтичане на токена, ако нямаме, това означава, че потребителят никога не е влизал. Ние пренасочваме потребителя към страницата за вход.
  2. Ако има дата на изтичане на токена, ние го проверяваме, за да проверим дали е изтекъл или ще изтече през следващите 10 минути. Ако някое от гореспоменатите условия е вярно, ние пренасочваме потребителя към влизане. 10-те минути са само буфер, който си позволяваме, за да опресним токена. В действителност може да е по всяко време преди изтичането на токена.
  3. Ако 1 и 2 не са валидни, тогава знаем, че токенът все още е валиден и можем да го използваме още известно време. На този етап настройваме setTimeoutза опресняване на токена 10 минути преди действителното му изтичане.

Функцията refreshToken — не е изненадващо — всъщност опреснява токена. Методът за извършване на това в auth0 sdk се нарича checkSession Механиката на това как Auth0 прави това без пренасочване може да се намери тук — интересен подход. След опресняване на токена, задаваме друго време за изчакване, за да опресним бутона отново 10 минути преди да изтече.

Трябва да извикаме initSession при зареждане на приложението, за да настроим сесията. Най-доброто място да направите това е в нашия основен Vue компонент, App.vue:

//App.vue

//irrelevant code omitted
<script>

    import Router from "./router";
    import Store from "./store";
    import {initSession} from "./session-manager";

    export default {
        name: 'app',
        data() {
            return {};
        },
        mounted() {
            initSession();  //Initialize our session
        },
        router: Router,
        store: Store
    };


</script>
//irrelevant code omitted

Ще оставя излизането от приложението на потребителя. (Съвет: извикайте метода за излизане на Auth0 sdk, изчистете токените localstorage и изчистете времето за изчакване на маркера за опресняване)

И това е всичко. Вече можем да бъдем сигурни, че сесиите на нашите потребители няма да бъдат прекъсвани ненужно и не трябваше да съхраняваме токени за опресняване, за да постигнем това.