How to efficiently store and use authentication in Ionic 3

I am currently developing an Ionic (3.4) application for iOS / Android. I am not familiar with authentication processes or applications.

After using the HTTP request from the provider, I get my object , the user. But I have no idea how to store it or deal with it. What are some good practices:

  • Suppose I just saved an object in a provider and called every page that I have?
  • I suppose storing it as a kind of global object in the application?
  • Or do I suppose (as below) to pass it as a navigation variable from one page to another? (I think this is not the right answer)

And finally, how the application will respond to reboot / reboot: how to avoid re-filling the form?

Here is my service:

@Injectable()
export class UserProvider {
    data = {};
    username: string;
    password: string;

    constructor(private _http: Http) {
        console.log('Hello UserProvider Provider');
    }

    getUser(username:string, password:string){

        let urlSearchParams = new URLSearchParams();
        urlSearchParams.append('username', username);
        urlSearchParams.append('password', password);
        let params = urlSearchParams.toString()

        var headers = new Headers();
        headers.append('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');

        return this._http
        .post("http://api.minesdedouai.fr/user/login", params, {headers:headers} )
        .map(response => response.json())

    }

}

I know that it’s supposed to use some token in the login request, but, as I said, this is a small student API, we are not talking about it and are working.

And this is the method that uses the service, somewhere in the component (page).

onLogin(form: NgForm) {
  if (form.valid) {
    this._userProvider.getUser(this.login.username, this.login.password)
    .subscribe((response) => {
      this.user = response;
      console.log("Authentification Success");
      this.navCtrl.push(TabsPage, {user: this.user});
    },
    (error) => {
      if (error.status===403){
        console.log("Wrong User")
      }
      else{
        console.log(error);
      }

    });
  }
}

Many thanks

+4
source share
2 answers

I will tell you how I feel about authentication in my ionic application.

The first step is to create a view of the data you want to save. I used to store some user data and a jwt token for authentication.

user.ts:

export class AuthenticatedUser {
  private _username: string;
  private _id: number;
  private _token: string;

  public static GetNewInstance(): AuthenticatedUser {
    return new AuthenticatedUser(null, null, null)
  }

  public static ParseFromObject(object): AuthenticatedUser {
    const model = AuthenticatedUser.GetNewInstance();

    if (object) {
      model.username = object.username;
      model.id = object.id;
      model.token = object.token;
    }

    return model;
  }

  constructor(username: string, id: number, token: string) {
    this._username = username;
    this._id = id;
    this._token = token;
  }

  get username(): string {
    return this._username;
  }

  set username(value: string) {
    this._username = value;
  }

  get id(): number {
    return this._id;
  }

  set id(value: number) {
    this._id = value;
  }

  get token(): string {
    return this._token;
  }

  set token(value: string) {
    this._token = value;
  }
}
  • GetNewInstance AuthenticatedUser.
  • ParseFromObject AuthenticatedUser . api object .

. - UserService. AuthenticatedUser . .

user.service.ts:

export class UsersService {

  private _user: Subject<AuthenticatedUser> = new Subject<AuthenticatedUser>();

  constructor(private storage: Storage) {}

  /* ---------------------------------------------------------------------------------------------------------------- */
  /* Observable use object                                                                                            */

  public subscribeToUserService(callback) {
    return this._user.subscribe(callback);
  }

  public updateUserService(user: AuthenticatedUser) {
    this._user.next(user);
  }

  /* ---------------------------------------------------------------------------------------------------------------- */
  /* User storage management                                                                                          */

  /**
   * Write user properties in the local storage.
   *
   * @param user
   * @returns {Promise<AuthenticatedUser>}
   */
  createOnStorage(user: AuthenticatedUser): Promise<AuthenticatedUser> {
    return new Promise((resolve) => {
      this.getOnStorage().then((res) => {
        if (res) {
          this.deleteOnStorage().then(() => {

          });
        }
      }).then(() => {
        this.updateUserService(user);
        this.storage.set('user', JSON.stringify(user));
        resolve();
      });
    });
  }

  /**
   * Get user properties from local storage.
   *
   * @returns {Promise<AuthenticatedUser>}
   */
  getOnStorage(): Promise<AuthenticatedUser> {
    return new Promise((resolve) => {
      this.updateUserService(JSON.parse(this.storage.get('user')));
      resolve(this.storage.get('user'));
    });
  }

  /**
   * Get user properties from local storage.
   *
   * @returns {Promise<AuthenticatedUser>}
   */
  getOnStorageSync() {
    this.updateUserService(JSON.parse(this.storage.get('user')));
    return this.storage.get('user');
  }

  /**
   * Update user properties from local storage.
   *
   * @param user
   * @returns {Promise<AuthenticatedUser>}
   */
  updateOnStorage(user: AuthenticatedUser): Promise<AuthenticatedUser> {
    return new Promise((resolve) => {
      resolve(this.storage.get('user'));
    });
  }

  /**
   * Delete user properties from local storage.
   *
   * @returns {Promise<AuthenticatedUser>}
   */
  deleteOnStorage(): Promise<AuthenticatedUser> {
    return new Promise((resolve) => {
      this.storage.clear();
      resolve();
    });
  }
}

ApiService. HTTP . authenticatedUser.

@Injectable()
export class ApiService {

  private baseUrl = "https://my.api.co";
  private user: AuthenticatedUser;  


  /* ---------------------------------------------------------------------------------------------------------------- */

  constructor(private userService: UserService, private http: Http) {
     getAuthUser()
  }

   private getAuthUser() {
     this.userService.getOnStorage.then(
       (user) => {
         this.user = user;
       });      
   }

   /**
   * Get the Json Web Token from the local storage.
   *
   * @returns {RequestOptions}
   */
  private formatHeader(): RequestOptions {
    const headers: Headers = new Headers();
    if (this.user.token) {
      headers.append('Authorization', 'Bearer ' + this.user.token);
    }
    return new RequestOptions({headers});
  }

  /**
   * Get the body of an HTTP response.
   *
   * @param res
   * @returns {any|{}}
   */
  private handleBody(res: Response) {
    return res.json() || {};
  }

  /**
   * Format the error message of an HTTP response.
   *
   * @param error
   * @returns {any}
   */
  private handleError(error: Response | any) {
    let errorModel: any = {};

    if (error instanceof Response) {
      const body = error.json() || '';
      const err = body.error || JSON.stringify(body);

      errorModel = { status: error.status, message: `${error.status} - ${err.cause} ` };
    } else {
      errorModel = { status: error.status, message: error.toString()};
    }
    return Observable.throw(errorModel);
  }
  /* ---------------------------------------------------------------------------------------------------------------- */

  /**
   * Perform a PUT request.
   *
   * @param url
   * @param auth
   * @param body
   * @returns {Observable<>}
   */
  putRequest(url: string, body: Object, auth: boolean = true): Observable<Object> {
    let header = null;

    if (auth) {
      header = ApiService.formatHeader();
    }
    return this.http.put(this.BASE_URL + url, body, header)
      .map(ApiService.handleBody)
      .catch(ApiService.handleError);
  }

  /**
   * Perform a POST request.
   *
   * @param url
   * @param auth
   * @param body
   * @returns {Observable<>}
   */
  postRequest(url: string, body: Object, auth: boolean = true): Observable<Object> {
    let header = null;

    if (auth) {
      header = ApiService.formatHeader();
    }
    return this.http.post(this.BASE_URL + url, body, header)
      .map(ApiService.handleBody)
      .catch(ApiService.handleError);
  }

  /**
   * Perform a HEAD request.
   *
   * @param url
   * @param auth
   * @returns {Observable<>}
   */
  headRequest(url: string, auth: boolean = true): Observable<Object> {
    let header = null;

    if (auth) {
      header = ApiService.formatHeader();
    }
    return this.http.head(this.BASE_URL + url, header)
      .map(ApiService.handleBody)
      .catch(ApiService.handleError);
  }

  /**
   * Perform a GET request.
   *
   * @param url
   * @param auth
   * @returns {Promise<>}
   */
  getRequest(url: string, auth: boolean = true): Observable<Object> {
    let header = null

    if(auth) {
      header = ApiService.formatHeader();
    }

    return this.http.get(this.BASE_URL + url, header)
      .map(ApiService.handleBody)
      .catch(ApiService.handleError);
  }

  /**
   * Perform a DELETE request.
   *
   * @param url
   * @param auth
   * @returns {Observable<>}
   */
  deleteRequest(url: string, auth: boolean = true): Observable<Object> {
    let header = null;

    if (auth) {
      header = ApiService.formatHeader();
    }
    return this.http.delete(this.BASE_URL + url, header)
      .map(ApiService.handleBody)
      .catch(ApiService.handleError);
  }

- AuthService. /.

auth.service.ts:

@Injectable()
export class AuthService {
   private user: AuthenticatedUser;
  /* ---------------------------------------------------------------------------------------------------------------- */

  constructor(private userService: userService, private apiService: ApiService) {
  this.getAuthUser();
}
   getAuthUser() {
     this.userService.getOnStorage().then(
        (user) => {
          this.user = user;
        }
     );
   }

  /* ---------------------------------------------------------------------------------------------------------------- */

  /**
   * Request an authentication access.
   *
   * @param email the email of the user
   * @param password the password of the user
   * @returns {Promise<any>}
   */
  login(email: string, password: string): Promise<AuthentificatedUser> {
    return new Promise((resolve, reject) => {
      this.apiService.postRequest('/auth', {email: email, password: password})
        .subscribe(
          res => resolve(AuthentificatedUser.ParseFromObject(res)),
          error => reject(<any>error));
    });
  }

  /**
   * Logout a user from the authentication process.
   *
   * @returns {Promise<any>}
   */
  logout(): Promise<any> {
    return new Promise((resolve) => {
      this.userService.deleteOnStorage().then(() => {
        resolve();
      });
    });
  }


  /**
   * Check whether a user is already logged in.
   *
   * @returns {boolean}
   */
  isLoggedIn() {
    if (this.user.token) {
      return true;
    } else {
      return false;
    }
  }

  /* ---------------------------------------------------------------------------------------------------------------- */
}

:

this.authService.login('login', 'password').then(
  (user) => {
    this.userSerivce.createOnStorage(user);
    this.navCtrl.push(HomePage);
  }).catch(
    (err) => {
      //show the error
    }
  );

, , , .

export HomePage() {
  private user: AuthenticatedUser;

  constructor(private userService: UserService) {
    this.getAuthUser();
  }

  private getAuthUser() {
    this.userService.getOnStorage().then(
      (user) => {
        this.user = user;

        if (!this.user.token) {
          this.navCtrl.push(LoginPage)
        }
      }
    );
  }
}
0

Source: https://habr.com/ru/post/1680836/


All Articles