Autenticação como Serviço — Criando uma aplicação utilizando Auth0 e Ionic2

Stefan Horochovec
horochovec
Published in
7 min readMay 4, 2016

Olá pessoal,

Nesse segundo artigo da série “Autenticação como Serviço”, vamos demonstrar o processo de criação de uma nova aplicação na Auth0.

Após autenticar-se na Auth0, você verá um menu bastante extenso com várias funcionalidades.

Para iniciarmos uma nova aplicação, procure a opção “Dashboard” e selecione a opção “+ New Application”.

Nesse exemplo iremos criar uma aplicação chamada “Todo App” para registro de atividades a serem feitas, um clássico exemplo :)

A tecnologia que iremos utilizar para esse projeto é o Ionic 2 beta, um framework destinado ao desenvolvimento de aplicações híbridas desenvolvido em Angular.

Primeiro, caso ainda não tenha o Ionic 2 beta instalado, utilize o seguinte comando para efetuar a instalação:

$ npm install -g ionic@beta

Agora, iremos criar um novo projeto Ionic utilizando o seguinte comando:

$ ionic start auth0-ionic --v2 -ts

Após a criação, podemos entrar no diretório:

$ cd auth0-ionic

E para testarmos a sua criação, podemos executar o seguinte comando:

$ ionic serve
√ Running dev server: http://192.168.1.13:8100
Ionic server commands, enter:
restart or r to restart the client app from the root
goto or g and a url to have the app navigate to the given url
consolelogs or c to enable/disable console log output
serverlogs or s to enable/disable server log output
quit or q to shutdown the server and exit

E como resultado:

Ok, até essa etapa, já iniciamos nossa aplicação no dashboard da Auth0, e iniciamos nosso projeto Ionic.

A próxima etapa, é adicionarmos o suporte a biblioteca angular2-jwt em nosso projeto. Iremos utilizá-la com o intuito de prover suporte a adição de um JWT (JSON Web Token) em nossos requests.

$ npm install angular2-jwt --save

O próximo passo, é adicionarmos as dependências provide, Http, AuthHttp e AuthConfig em nossa aplicação, para isso, adicione no arquivo app/app.ts as seguintes linhas:

...
import {provide} from 'angular2/core';
import {Http} from 'angular2/http';
import {AuthHttp, AuthConfig} from 'angular2-jwt';

E após essa adição, iremos configurar nosso provider no construtor da nossa aplicação

@App({
template: '',
config: {},
providers: [
provide(AuthHttp, {
useFactory: (http) => {
return new AuthHttp(new AuthConfig(), http);
},
deps: [Http]
}),
]
})
export class TodoApp {
...
}

Após essa etapa, iremos adicionar uma classe contendo as informações necessárias para nosso serviço de autenticação, para isso, iremos criar uma classe chamada config-auth0.ts dentro de nosso diretório app/.

Nessa classe, iremos adicionar as credenciais de segurança do nosso aplicativo, para obte-las, basta entrar na opção Settings da nossa aplicação, conforme imagem abaixo:

Após obtermos as credenciais, podemos adicioná-las em nossa classe config-auth0:

export class ConfigAuth0 {
static CLIENT_ID:string = "CLIENT_ID";
static AUTH0_DOMAIN:string = "DOMAIN_NAME";
}

Após configurarmos nossa classe que irá armazenar nossas credenciais, podemos iniciar a configuração do nosso serviço de autenticação, que será responsável pelos processos de login, logout e checar se o usuário está ou não logado na aplicação.

E também será responsável pela configuração do Lock. O Lock é mais um serviço disponibilizado pela Auth0. Sua utilização nos permite adicionarmos em nossa aplicação, uma tela de login que irá responder de acordo com as configurações adicionadas em nossa aplicação, como: Single Sign on, Social Logins, etc.

Para isso, iremos adicionar em nosso projeto uma classe chamada AuthService, localizada em: app/services/auth-service.ts

import {Storage, LocalStorage} from 'ionic-angular';
import {AuthHttp, JwtHelper, tokenNotExpired} from 'angular2-jwt';
import {Injectable, NgZone} from 'angular2/core';
import {Observable} from 'rxjs/Rx';
import {ConfigAuth0} from '../config-auth0.js';
declare var Auth0Lock: any;@Injectable()
export class AuthService {

jwtHelper: JwtHelper = new JwtHelper();
lock = new Auth0Lock(ConfigAuth0.CLIENT_ID, ConfigAuth0.AUTH0_DOMAIN);
local: Storage = new Storage(LocalStorage);
refreshSubscription: any;
user: Object;
zoneImpl: NgZone;

constructor(private authHttp: AuthHttp, zone: NgZone) {
this.zoneImpl = zone;
this.local.get('profile').then(profile => {
this.user = JSON.parse(profile);
}).catch(error => {
console.log(error);
});
}

public authenticated() {
return tokenNotExpired();
}

public login() {
this.lock.show({
authParams: {
scope: 'openid offline_access',
device: 'Mobile device'
}
}, (err, profile, token, accessToken, state, refreshToken) => {
if (err) {
alert(err);
}
this.local.set('profile', JSON.stringify(profile));
this.local.set('id_token', token);
this.local.set('refresh_token', refreshToken);
this.zoneImpl.run(() => this.user = profile);
});
}

public logout() {
this.local.remove('profile');
this.local.remove('id_token');
this.local.remove('refresh_token');
this.zoneImpl.run(() => this.user = null);
}
}Após configurarmos nosso serviço de autenticação e o Lock, iremos adicionar o Lock em nossa index.html, para que nossa aplicação inicie com a tela de login ao sistema. Para isso, iremos modificar o arquivo www/index.html adicionando o conteúdo logo acima da tag :....Agora, iremos adicionar na nossa classe principal (app.ts) o Provider AuthService:import {App, Platform} from 'ionic-angular';
import {StatusBar} from 'ionic-native';
import {TabsPage} from './pages/tabs/tabs';
import {provide} from 'angular2/core';
import {Http} from 'angular2/http';
import {AuthHttp, AuthConfig} from 'angular2-jwt';
import {AuthService} from './services/authservice';
@App({
template: '',
config: {},
providers: [
provide(AuthHttp, {
useFactory: (http) => {
return new AuthHttp(new AuthConfig(), http);
},
deps: [Http]
}), AuthService]
})
export class TodoApp {
....
}
Ok, após essa etapa, iremos adicionar o suporte ao Social Login via Auth0. Para isso, iremos selecionar a opção Connections, Social, e habilitar a opção Twitter.
Após isso, em uma nova janela no seu navegador abra o Application Management do Twitter e selecione a opção "Create New App".
Após abrir a janela e preencher as informações básicas, devemos ficar atentos ao Callback URL. Esse campo deverá ser preenchido da seguinte maneira: http://[SEU-LOGIN-AUTH0].auth0.com/login/callbackApós confirmas as informações, iremos obter as informações de API Key e API Secret na opção Keys and Access Tokens, conforme imagem:
Obtendo essas informações, iremos adicionar as mesmas na configuração do Twitter no painel de controle da Auth0:
Agora, iremos adicionar uma página, que irá demonstrar o perfil de nosso usuário logado, e caso não tenha sido autenticado, irá solicitar que o usuário efetue o login na aplicação, para isso, iremos adicionar um diretório chamado perfil dentro da diretório pages, e adicionar dois arquivos: perfil.html e perfil.ts. Também iremos remover as pastas page1, page2, page3 e tabs no diretório pages.No arquivo perfil.ts, iremos adicionar o seguinte conteúdo:import {Page} from 'ionic-angular';
import {AuthService} from '../../services/authservice';
@Page({
templateUrl: 'build/pages/perfil/perfil.html',
})
export class PerfilPage {

constructor(private auth: AuthService) {

}

}
No arquivo perfil.html iremos adicionar o seguinte conteúdo:ProfileLogin{{ auth.user.nickname }}{{ auth.user.email }}LogoutTambém iremos remover o conteúdo do arquivo app/theme/app.core.scss removendo o seguinte conteúdo:@import "../pages/page1/page1";
@import "../pages/page2/page2";
@import "../pages/page3/page3";
E por fim, iremos alterar o arquivo app/app.ts nas seguintes linhas,Linha 3import {PerfilPage} from './pages/perfil/perfil';Linha 21rootPage: any = PerfilPage;Nessa etapa via command line, iremos adicionar o plugin cordova-plugin-inappbrowser, conforme abaixo:$ ionic plugin add cordova-plugin-inappbrowserAgora, podemos gerar uma versão do nosso aplicativo para testá-lo em nosso device, para isso, iremos executar a seguinte instrução para Android:$ ionic build android
Running 'build:before' gulp task before build
[20:50:01] Starting 'clean'...
[20:50:01] Finished 'clean' after 23 ms
[20:50:01] Starting 'build'...
[20:50:01] Starting 'sass'...
....
BUILD SUCCESSFUL
Total time: 3.956 secs
Built the following apk(s): /Users/horochovec/Projects/horochovec/auth0-ionic/platforms/android/build/outputs/apk/android-debug.apk
Após essa etapa, podemos partir para a instalação do APK em nosso device para testes.Tela de login:
Tela de autorização:
E após efetuarmos nosso login, podemos listar nosso primeiro usuário adicionado a nossa conta na Auth0:
Como ultima etapa do nosso aplicativo, iremos adicionar o suporte de refresh-token em nosso AuthService, conforme as seguintes alterações no arquivo app/services/authservice.ts:Adicionar o seguinte conteúdo:public scheduleRefresh() {
let source = this.authHttp.tokenStream.flatMap(
token => {
let jwtIat = this.jwtHelper.decodeToken(token).iat;
let jwtExp = this.jwtHelper.decodeToken(token).exp;
let iat = new Date(0);
let exp = new Date(0);
let delay = (exp.setUTCSeconds(jwtExp) - iat.setUTCSeconds(jwtIat));return Observable.interval(delay);
});
this.refreshSubscription = source.subscribe(() => {
this.getNewJwt();
});
}
public startupTokenRefresh() {
if (this.authenticated()) {
let source = this.authHttp.tokenStream.flatMap(
token => {
let now: number = new Date().valueOf();
let jwtExp: number = this.jwtHelper.decodeToken(token).exp;
let exp: Date = new Date(0);
exp.setUTCSeconds(jwtExp);
let delay: number = exp.valueOf() - now;
return Observable.timer(delay);
});
source.subscribe(() => {
this.getNewJwt();
this.scheduleRefresh();
});
}
}
public unscheduleRefresh() {
if (this.refreshSubscription) {
this.refreshSubscription.unsubscribe();
}
}
public getNewJwt() {
this.local.get('refresh_token').then(token => {
this.lock.getClient().refreshToken(token, (err, delegationRequest) => {
if (err) {
alert(err);
}
this.local.set('id_token', delegationRequest.id_token);
});
}).catch(error => {
console.log(error);
});
}
E corrigir os métodos login() e logout() conforme abaixo:public login() {
this.lock.show({
authParams: {
scope: 'openid offline_access',
device: 'Mobile device'
}
}, (err, profile, token, accessToken, state, refreshToken) => {
if (err) {
alert(err);
}
this.local.set('profile', JSON.stringify(profile));
this.local.set('id_token', token);
this.local.set('refresh_token', refreshToken);
this.zoneImpl.run(() => this.user = profile);
this.scheduleRefresh();
});
}

public logout() {
this.local.remove('profile');
this.local.remove('id_token');
this.local.remove('refresh_token');
this.zoneImpl.run(() => this.user = null);
this.unscheduleRefresh();
}
E por fim, em nossa classe principal app/app.ts, adicionar a solicitação para o refreshtoken no momento que a aplicação estiver disponível para o usuário:export class TodoApp {
rootPage: any = PerfilPage;
constructor(platform: Platform, private authHttp: AuthHttp, private auth: AuthService) {
platform.ready().then(() => {
StatusBar.styleDefault();
this.auth.startupTokenRefresh();
});
}
}
Todo o código deste exemplo pode ser verificado no Github.E o aplicativo para Android pode ser feito o Download via Play Store, clicando aqui.

--

--