• Post last modified:06/04/2020
  • Post Category:FrontOps
  • Post Comments:1 Komentarz

Dwa poprzednie wpisy (1) (2) dotyczące przydatnych nam usług dostępnych na AWS nauczyły nas jak możemy zbudować całkiem profesjonalną infrastrukturę dla naszej aplikacji nie posiadając żadnych serwerów bądź dedykowanych narzędzi CI/CD. Dołożymy do tego dzisiaj kolejne „cegiełki” a mianowicie autoryzację, GraphQL i framework dzięki któremu dodawanie kolejnych funkcjonalności do naszej aplikacji stanie się niezwykle łatwe, czyli AWS Amplify.

Autoryzacja

Możliwość rejestracji a następnie logowanie się na swoje konto jest jedną z podstawowych funkcjonalności większości współczesnych aplikacji. Mimo to samodzielne tworzenie takiego mechanizmu w dalszym ciągu potrafi być dość trudnym i czasochłonnym zadaniem. Czasami lepszym i wydajniejszym rozwiązaniem może okazać się skorzystanie z gotowego narzędzia które będzie odpowiedzialne za autentykację i autoryzację naszych użytkowników. Taką usługą w świecie AWS jest Cognito.

Cognito jest kompleksowym rozwiązaniem dzięki któremu możemy dodać możliwość rejestracji nowych oraz logowania istniejących użytkowników. Główną funkcjonalnością Cognito są tzw. User pools, czyli miejsce w którym przechowujemy wszystkie informacje dotyczące zarejestrowanych użytkowników, tj. email, login, hasło, numer telefonu, itp. Możemy tutaj przypisywać do naszych użytkowników tak dużo atrybutów jak nam się tylko podoba. Przykładowymi atrybutami mogą być informacje o wykupionej subskrypcji, rodzaj użytkownika, itp. Wewnątrz User pools możemy tworzyć grupy i przypisywać im odpowiednie uprawnienia.

Cognito również dostarcza nam takie funkcjonalności jak MFA (Multi-Factor Authentication), gdzie możemy dodać dodatkową warstwę ochrony. Służy do tego np. wysyłanie użytkownikom SMS’a z jednorazowym kodem przy próbie zalogowania, czy weryfikację maila. To co najważniejsze – wysyłką SMS, maila oraz weryfikacją klikniętego linka zajmuje się Cognito. Nasza praca sprowadza się do kliknięcie w odpowiednie miejsce podczas tworzenia User Pool.

Oprócz standardowego sposobu logowania poprzez login/hasło, możemy dać naszym użytkownikom możliwość logowania się przy użyciu konta np. Gmail, Facebook czy Amazon. Nie mamy wtedy dużo informacji na temat naszego użytkownika, jednak możemy dotrzeć do bardzo dużej grupy potencjalnych userów.

Rzeczą wartą odnotowania jest to, iż w przypadku gdy nasza aplikacja korzysta z wielu usług AWS, dostęp do poszczególnych usług można również oprzeć o Cognito. Przykładami takich usług mogą być S3 (storage), DynamoDB (baza danych, odczyt informacji) czy API Gateway (API endpoint).

Wtedy proces otrzymywania dostępu będzie wyglądał następująco (dokumentacja AWS): CognitoDiagram

AWS Amplify

W pierwszym wpisie dotyczącym AWS napisałem, że jedną z moich ulubionych usług z portfolio AWS jest Lambda. Teraz doszliśmy do kolejnej – AWS Amplify. Zanim napiszę czym jest Amplify wyobraźmy sobie sytuację w której mamy do zbudowania jakąś standardową aplikację, w której nasi użytkownicy mają możliwość logowania się na swoje konta oraz tworzenia i zapisywania notatek. Dodatkowo chcemy wiedzieć ilu użytkowników korzysta z naszej aplikacji i jakie czynności w niej wykonują najczęściej.

Jesteśmy już po lekturze dwóch postów na temat AWS, więc decydujemy się zbudować wszystko w oparciu o chmurę Amazona. Wiemy też, że JavaScript powinien nam wystarczyć do zaimplementowania wszystkich w/w funkcjonalności. Po wielu godzinach rozmyślania decydujemy się na stack:

  • React jako biblioteka po stronie front-endu,
  • S3 jako miejsce do hostowania zbudowanej aplikacji oraz wszystkich innych assetów,
  • Cognito jako serwis do zarządzania autoryzacją,
  • AppSync jako GraphQL API,
  • DynamoDB (razem z Lambdą i API Gateway) jako baza danych do przechowywania notatek,
  • Pinpoint (albo Google Analytics) do zbierania danych dotyczących użytkowania aplikacji.

Dla ułatwienia odpuśćmy sobie kwestie dotyczące CI/CD.

Teraz zostaje nam „tylko” zintegrować ze sobą wszystkie te usługi. Możemy tutaj skorzystać z przygotowanego SDK, które mocno ułatwi nam pracę. Dokumentacja oraz liczne przykłady i tutoriale pozwolą nam to osiągnąć pewnie dość szybko, ale jednak trochę czasu nad tym spędzimy.

No to teraz wchodzi on – Amplify, cały na.. pomarańczowo, wnioskując po kolorach na oficjalnej stronie:).

Tak więc do rzeczy – czym jest i do czego służy AWS Amplify?

O AWS Amplify możemy myśleć trochę jak o usłudze back-end as a service. Amplify dzieli się na trzy główne składowe:

  • CLI Toolchain
  • Client Library
  • Console

CLI Toolchain

Dzięki CLI Toolchain, możemy w niezwykle łatwy sposób tworzyć/edytować/usuwać usługi AWS, których chcemy użyć w naszej aplikacji. Wszystko odbywa się z wiersza poleceń i integracja z naszą aplikacją wybranych przez nas usług jest tak prosta jak dodanie biblioteki z npm do aplikacji Reactowej. Przykładowo – dodanie autoryzacji do aplikacji sprowadza się do wywołania komendy amplify add auth. Więcej szczegółów już za chwilę.

Client Library

Client Library jest zestawem bibliotek przygotowanym pod najpopularniejsze obecnie biblioteki front end-owe (React, React Native, VUE, Angular), który bardzo ułatwia nam komunikację między usługami stworzynymi przez CLI Toolchain a frontową warstwą naszej aplikacji, czyli np. Reactem. Wszystkie te biblioteki są udostępnione na licencji Open Source, więc mamy tutaj bardzo duże wsparcie community. Oczywiście AWS Amplify będzie działało nam bardzo dobrze z każdą aplikacją stworzoną w JavaScript, jednak wtedy nie będziemy mogli użyć omawianych teraz bibliotek i czeka nas trochę więcej pracy.

Console

Tutaj mamy wszystko co związane z CI/CD. Z Console możemy połączyć nasze repozytorium (GitHub, GitLab, BitBucket) i skonfigurować w taki sposób, aby każdy nowy commit pojawiający się w wybranej przez nas gałęzi uruchamiał build i deployment aplikacji. Tego tematu nie będziemy dzisiaj poruszać jakoś bardziej szczegółowo.

Mamy już ogólne pojęcie czym jest Amplify, więc bierzmy się za dodawanie kolejnych funkcjonalności do naszej aplikacji z notatkami.

Logowanie

Przeanalizujemy teraz w jaki sposób w zaledwie kilka minut jesteśmy w stanie dodać funkcjonalność logowania:

  1. Instalujemy CLI: npm install -g @aws-amplify/cli.
  2. Konfigurujemy CLI (musimy posiadać konto AWS i najlepiej być już zalogowani w przeglądarce): amplify configure. Konfigurator poprowadzi nas „za rękę” przez konfigurację otwierając w przeglądarce właściwe strony z których będzimy musieli skopiować hasła i klucze.
  3. Tworzymy nową aplikację na bazie CRA: npx create-react-app my-app.
  4. Wewnątrz nowo stworzonej aplikacji inicjujemy Amplify: amplify init. Pojawi nam się kilka pytań na podstawie których Amplify stworzy odpowiedni plik konfiguracyjny.
  5. Dodajemy bibliotekę, która ułatwi nam komunikację pomiędzy usługami AWS a React: yarn add aws-amplify aws-amplify-react.
  6. Dodajemy usługę autoryzacji (Cognito): amplify add auth.
  7. Tworzymy nową usługę Cognito na naszym koncie AWS: amplify push. Koniec, back-endowa część usługi autoryzacyjnej została właśnie stworzona i możemy używać jej na froncie:)
  8. Przechodzimy do edytora tekstowego i w naszej aplikacji edytujemy dwa pliki: index.js oraz App.js:
import React from 'react'; 
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';

import Amplify from 'aws-amplify'  // dodajemy Amplify do aplikacji
import config from './aws-exports' // importujemy stworzoną automatycznie przez Amplify CLI konfigurację
Amplify.configure(config)  // konfigurujemy Amplify

ReactDOM.render(<App />, document.getElementByID('root'))
registerServiceWorker();
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

import { withAuthenticator } from 'aws-amplify-react'  // HOC do sprawdzania czy mamy zalogowanego użytkownika

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Welcome to React</h1>
        </header>
        <p className="App-intro">
          To get started, edit <code>src/App.js</code> and save to reload.
        </p>
      </div>
    );
  }
}

export default withAuthenticator(App, { includeGreetings: true});  // dodajemy autoryzację na całą naszą aplikację. "includeGreetings" wygeneruje nam górną belkę z nazwą użytkownika i przyciskem "Wyloguj"

Teraz możemy uruchomić naszą aplikację npm start, stworzyć pierwszego użytkownika i sprawdzić poprawność działania autoryzacji.

AWS Amplify stworzył oraz zintegrował usługę Cognito z naszą aplikacją, ale oczywiście możemy zalogować się do konsoli AWS, wyszukać utworzony user pool w Cognito i dowolnie go konfigurować wedle naszych potrzeb.

API

Dodajmy sobie jeszcze GraphQL API i bazę danych. Ponownie – cała trudność sprowadza się do wpisania w konsoli amplify add api. Pamiętajmy, aby być w głównym katalogu projektu CRA. Kolejny zestaw krótkich pytań, wywołanie amplify push i GraphQL API (AppSync) gotowe. Teraz możemy wejść w panel usługi AppSync przez przeglądarkę, wyszukać przed chwilą stworzone API i podejrzeć automatycznie wygenerowane schema jak również wykonać kilka testowych queries i mutations na naszym API.

Wracamy znowu na front. Przerabiamy nieco nasz komponent App.js i teraz może on wyglądać następująco:

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

import { withAuthenticator } from 'aws-amplify-react'
import { API, graphqlOperation } from 'aws-amplify' // dodajemy komunikację z API na froncie

// Pytamy API o listę wszystkich notatek
const ListNotes = ` 
  query { 
    listNotes {
      items { 
        id title description importance 
      }
    }
  }
`

class App extends Component {
  state = { notes: [] }  // listę notatek trzymamy w stanie komponentu

  async componentDidMount () {
    const noteDate = await API.graphql(graphqlOperation(ListNotes)) // pobieramy notatki
    this.setState({ notes: noteData.data.listNotes.items })  // i zapisujemy do stanu
  }

  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Welcome to React</h1>
        </header>
        {
          this.state.notes.map((note, i)) => (  // wyświetlamy wszystkie notatki
            <div>
              <h3>{note.title}</h3>
              <p>{note.description}</p>
              <p>{note.importance}</p>
            </div>
          ))
        }
      </div>
    );
  }
}

export default withAuthenticator(App, { includeGreetings: true});

Hosting

Ostatnia rzecz jaką sobie wspólnie dołożymy do tej aplikacji to hosting na S3. Powtarzamy to co już znamy, czyli komenda amplify add hosting, kilka pytań, komenda amplify publish i powinna nam się uruchomić nowa karta przeglądarki z uruchomioną aplikacją serwowaną z bucketa S3.

Co dalej?

W tym krótkim poradniku pokazał w jaki sposób możemy ułatwić sobie pracę nad naszą aplikacją z użyciem frameworku AWS Amplify. Skorzystaliśmy z trzech najbardziej podstawowych funkcjonalności, czyli auth, api i hosting. Tych funkcjonalności jest oczywiście dużo więcej (np. analytics, notyfikacje push dla aplikacji mobilnych, storage, czy nawet AR/VR lub Chat Bots).

Informacje o wszystkich możliwościach Amplify znajdziemy na oficjalnej stronie projektu.

Kamil Józwik

Front end developer👨‍💻 Autor małego narzędzia dla programistów - frontbook.dev oraz autor kolejnych postów na tym blogu. Ulubiony stack to React wraz z TypeScript oraz wszystko co "nowe" w tym pięknym dynamicznym front end-owym świecie 🙂

Ten post ma jeden komentarz

  1. Marek

    Hej, świetna seria. Może zbyt dużo nie szukałem, ale w końcu znalazłem przystępną serię o produktach aws 😉 Fajnie to opisałeś i czekam na więcej wpisów!

Dodaj komentarz