javascriptangulartypescript

Angular - Nothing is local storage after successful user login


In my Angular-13 frontend and ASP.NET Core Web API, after successful login, I want to store User details into the localstorage.

From POSTMAN, I have this:

{
   "status_code": 200,
   "message": "Successfully Logged In",
   "result": {
       "token": "gggggffffffffffffdddddddddddd",
       "user": {
           "id": 3,
           "user_name": "smith",
           "last_login": "2022-01-03T12:35:26.0305649"
          },
       "roles": [
           "Teacher"
       ],
   }
}

Angular:

user.ts:

export interface IUser {
  userName?: string;
  lastLogin?: Date;
  token?: string;
  roles?: string[];
  expires?: Date;
}

auth.service.ts:

export class AuthService {
  baseUrl = environment.apiUrl;
  private currentUserSource = new ReplaySubject<IUser>(1);
  currentUser$ = this.currentUserSource.asObservable();

  constructor(private http: HttpClient, private router: Router) { }

  login(model: any){
    return this.http.post(this.baseUrl+'auth/login', model).pipe(
      map((res: IUser)=>{
        const user = res;
        if(user){
          this.setCurrentUser(user);
        }
      })
    )
  }

  setCurrentUser(user: IUser){
    if(user){
      user.roles = [];
      const roles = this.getDecodedToken(user.token).role;//copy token to jwt.io see .role
      Array.isArray(roles) ? user.roles = roles : user.roles.push(roles);
      localStorage.setItem('user', JSON.stringify(user));
      this.currentUserSource.next(user);
    }
  }

  getDecodedToken(token: string) {
    return JSON.parse(atob(token.split('.')[1]));
  }
}

On Angular frontend, I have two dashboards: teacher-dashboard and student-dashboard

auth.component:

createForm() {
  this.loginForm = new FormGroup({
    UserName: new FormControl('', Validators.required),
    Password: new FormControl('', [Validators.required, Validators.minLength(6), Validators.maxLength(80)])
  })
}

login(){
  this.authService.login(this.loginForm.value).subscribe(res=>{
    this.router.navigateByUrl('/');
  }, error=>{
    this.toastr.error(error.error);
  })
}

setCurrentUser is used to store user details in the LocalStorage.

However, after successful login I checked the LocalStorage (Application/LocalStorage) using inspect. It stores nothing there.

Where did I miss it and how do I correct that?

Thanks

console.log(res) gives:

Object
  message: "Successfully Logged In"
  result:
    expires: "2022-01-05T12:01:35Z"
    roles: ['Admin']
    token: "This is the token"
    user:
      id: 1
      is_password_changed: false
      last_login: "2022-01-05T09:46:24.7719569"
      user_name: "admin"
  status_code: 200

Solution

  • map is not the solution. If you want to do something on the response and the still can subscribe that in another component you have to use tap instead. In your auth.service.ts do it like:

    login(model: any){
      return this.http.post(this.baseUrl + 'auth/login', model).pipe(tap((res: IUser) => {
        if (res) {
          this.setCurrentUser(res);
        }
      }));
    }
    

    You also defined IUser model as the input model for setCurrentUser but you are passing wrong type of input in the function so you will get nothing in the function because your input does not have any of the desired properties and all the other ones that it has will be droped because the property name is not defined in the model.