In questa lezione verranno illustrati i passi necessari per realizzare una schermata di autenticazione che sfrutti il social login di Twitter tramite il servizio Firebase Authentication.
Configurazione del PodFile
Per iniziare l’integrazione, aggiungiamo il pod del TwitterKit
attraverso la modifica del Podfile inizializzato in precedenza.
Apriamo il Podfile con un qualsiasi editor di testo e aggiungiamo il pod di Twitter.
target 'SocialLoginHMTLit' do
use_frameworks!
# Pods for SocialLoginHMTLit
pod 'TwitterKit'
end
Una volta salvato e chiuso il file, da terminale eseguire il comando:
pod install
In questo modo, effettueremo l’installazione della libreria nel progetto e per la creazione del nuovo workspace da usare per lo sviluppo. Al termine dell’installazione, il terminale mostrerà un output simile al seguente.
Modifica del file Info.plist
Per abilitare il meccanismo di autenticazione di Twitter, modifichiamo il file Info.plist aggiungendo le informazioni relative all’applicazione ottenute durante la fase di registrazione di questa sulla piattaforma.
Apriamo il file Info.plist come codice sorgente (tasto destro -> Apri come -> Codice sorgente) e aggiungiamo l’URL e i Queries scheme per abilitare il meccanismo di login.
<dict>
…
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>twitterkit-O4vU6hLMWS0AyAUfwghwydVpZ</string>
</array>
</dict>
</array>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>twitter</string>
<string>twitterauth</string>
</array>
</dict>
Modifica dell’AppDelegate
Importiamo adesso il TwitterKit
. Questo processo differisce in base al linguaggio utilizzato per lo sviluppo dell'applicazione.
Per Objective-C, basta semplicemente riportare nel .h quando segue:
#import <TwitterKit/TWTRKit.h>
Per Swift, invece, l’import della libreria deve essere effettuato in un apposito bridging header, che può essere creato mediante l’aggiunta di un nuovo file dummy (da cancellare una volta terminato il processo).
Aggiungiamo, quindi, un nuovo file basato sul template Cocoa Touch Class e inseriamo il nome della classe selezionando come linguaggio Objective-C.
A questo punto, Xcode chiederà di creare o meno un Bridging Header. Clicchiamo sul bottone di creazione per far generare a Xcode il file SocialLoginHMTLit-Bridging-Header.h in cui riportare il precedente import.
Spostiamoci ora all’interno dell’AppDelegate e inizializziamo il TwitterKit
passando all’istanza di Twitter
la consumerKey
e il consumerSecret
(ottenuti nella lezione 4).
Swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
. . .
Twitter.sharedInstance().start(withConsumerKey:"O4vU6hLMWS0AyAUfwghwydVpZ", consumerSecret:"rVefL1c4foFzPkyypJ48xP0l2NfaCu594YBySsxyGIwqjpNYE7")
return true
}
Objective-C
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
. . .
[[Twitter sharedInstance] startWithConsumerKey:@"O4vU6hLMWS0AyAUfwghwydVpZ" consumerSecret:@"rVefL1c4foFzPkyypJ48xP0l2NfaCu594YBySsxyGIwqjpNYE7"];
}
Successivamente, per gestire il redirect del login, deve essere implementato il metodo application:openURL:options:
Swift
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
return Twitter.sharedInstance().application(app, open: url, options: options)
}
Objective-C
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options {
return [[Twitter sharedInstance] application:app openURL:url options:options];
}
Integrazione del bottone di login
Il modo più semplice per aggiungere il bottone di login è di definire nel metodo viewDidLoad
del ViewController
una nuova istanza del TWTRLogInButton
.
Per farlo, definiamo una variabile globale logInButton
:
Swift
var logInButton: TWTRLogInButton!
Objective-C
TWTRLogInButton *logInButton;
e modifichiamo il metodo viewDidLoad
come segue:
- inizializziamo un nuovo
TWTRLogInButton
con un blocco di completamento composto da unaTwitterSession
(la variabile session) eNSError
(la variabileerror
); - inseriamo nel blocco di completamento un controllo sullo stato della sessione per valutare se l’autenticazione è andata a buon fine;
- in caso di successo, estraiamo dalla sessione l’
authToken
e l’authTokenSecret
da utilizzare per la creazione delle credenziali tramite il metodocredential()
delTwitterAuthProvider
. - utilizziamo le credenziali così generate per effettuare il login con Firebase attraverso il metodo
signIn
della classeAuth
(responsabile dell’autenticazione delle app basate su Firebase); - se l’autenticazione è andata a buon fine, estraiamo le informazioni sull’utente, tra cui il nome utente.
Di seguito è riportata una possibile implementazione del loginButton
.
Swift
override func viewDidLoad() {
super.viewDidLoad()
logInButton = TWTRLogInButton(logInCompletion: { session, error in
if (session != nil) {
let authToken = session!.authToken
let authTokenSecret = session!.authTokenSecret
let credential = TwitterAuthProvider.credential(withToken: authToken, secret: authTokenSecret)
Auth.auth().signIn(with: credential) { (user, error) in
if let error = error {
print("error: \(error.localizedDescription)");
return
}
if let userName = user?.displayName{
print("hi \(userName)");
self.userIdLabel.text = "Hi \(userName)!"
}
self.toggleAuthUI()
}
} else {
print("error: \(String(describing: error?.localizedDescription))");
}
})
logInButton.center = self.view.center
self.view.addSubview(logInButton)
toggleAuthUI()
}
Objective-C
- (void)viewDidLoad {
...
TWTRLogInButton *logInButton = [TWTRLogInButton buttonWithLogInCompletion:^(TWTRSession *session, NSError *error) {
if (session) {
NSString *authToken = session.authToken;
NSString *authTokenSecret = session.authTokenSecret;
FIRAuthCredential *credential =
[FIRTwitterAuthProvider credentialWithToken:session.authToken
secret:session.authTokenSecret];
[[FIRAuth auth] signInAndRetrieveDataWithCredential:credential
completion:^(FIRAuthDataResult * _Nullable authResult,
NSError * _Nullable error) {
if (error) {
NSLog(@"error: %@", [error localizedDescription]);
return;
}
if (authResult == nil) { return; }
FIRUser *user = authResult.user;
self.userIdLabel.text = user.displayName
}];
...
} else {
NSLog(@"error: %@", [error localizedDescription]);
}
}];
logInButton.center = self.view.center;
[self.view addSubview:logInButton];
...
}
Una volta inizializzato il bottone, quest’ultimo viene aggiunto alla schermata corrente tramite il metodo addSubview
. Ovviamente, avendo aggiunto il bottone di login tramite codice, questo non sarà visibile nella Main.storyboard.
Aggiungiamo, ora, il bottone di logout.
Nella Main.storyboard, selezioniamo l'oggetto UIButton
dall’Object Library e posizioniamolo al centro della schermata. Successivamente, impostiamo il testo del bottone a log out) e lo sfondo a grigio attraverso la proprietà background dell’Attribute Inspector.
Colleghiamo poi il bottone con il codice del ViewController
per creare un IBOutlet
di tipo UIButton
e aggiungiamo un nuovo metodo per il logout da Twitter come segue.
Swift
@IBAction func didTapLogOut(_ sender: AnyObject) {
let store = Twitter.sharedInstance().sessionStore
if let userID = store.session()?.userID {
store.logOutUserID(userID)
}
let firebaseAuth = Auth.auth()
do {
try firebaseAuth.signOut()
} catch let signOutError as NSError {
print ("Error signing out: %@", signOutError)
}
. . .
}
Objective-C
- (IBAction)didTapSignOut:(id)sender {
TWTRSessionStore *store = [[Twitter sharedInstance] sessionStore];
NSString *userID = store.session.userID;
[store logOutUserID:userID];
NSError *signOutError;
BOOL status = [[FIRAuth auth] signOut:&signOutError];
if (!status) {
NSLog(@"Error signing out: %@", signOutError);
return;
}
. . .
}
Colleghiamo quindi il bottone di logout al metodo didTapLogOut
.
Analogamente, inseriamo una label di tipo UILabel
per mostrare il nome dell’utente loggato posizionandola sopra il bottone di logout e collegandola al codice, come fatto in precedenza.
Gestiamo infine, la visibilità dei bottoni creati e il testo e della label attraverso il seguente metodo.
Swift
func toggleAuthUI() {
if (Twitter.sharedInstance().sessionStore.hasLoggedInUsers()) {
logInButton.isHidden = true
logOutButton.isHidden = false
} else {
logInButton.isHidden = false
logOutButton.isHidden = true
userIdLabel.text = "Twitter Login"
}
}
Objective-C
- (void)toggleAuthUI {
if ([[Twitter sharedInstance].sessionStore hasLoggedInUsers]) {
self.logInButton.hidden = NO;
self.logOutButton.hidden = YES;
} else {
self.logInButton.hidden = YES;
self.logOutButton.hidden = NO;
self.userIdLabel.text = @"Twitter Login";
}
}
Questa funzione, nasconderà il bottone di login in caso di successo mostrando il bottone di logout. Contrariamente, in caso di fallimento o di logout, verrà visualizzato il bottone di login e reimpostato il testo della label.
Per completare le modifiche, richiamiamo toggleAuthUI
nel blocco di completamento del TWTRLogInButton
e nel metodo viewDidLoad
, come qui riportato.
Risultato finale
All’avvio dell’applicazione, viene mostrata la schermata iniziale contenente il bottone di default precedentemente aggiunto all’interfaccia e qui di seguito riportato.
Cliccando sul bottone, verrà richiesto all’utente di autenticarsi con il proprio account Twitter.
Una volta autenticato, l’utente viene rimandato nuovamente alla schermata iniziale dove al posto del bottone di login ci sarà quello di logout, come in figura.
Analogamente, cliccando sul bottone Log Out, la sessione dell’utente verrà cancellata e l’utente uscirà dall’applicazione ritornando alla sessione di login.
Il codice sorgente di questa sezione è reperibile su GitHub.