权限被拒绝使用Firebase身份验证登录

时间:2020-05-21 12:33:38

标签: angular typescript firebase-realtime-database firebase-authentication firebase-security

我在Angular项目中使用Firebase实时数据库。我有一个简单的卡片组数据库,我使用firebase auth API创建了一个简单的身份验证逻辑,我设置了如下数据库访问规则:

{
  "rules": {
    ".read": "auth != null",
    ".write": "auth != null"
  }
}

这是我在2个文件(服务和组件)中的身份验证逻辑,这是服务:

import { tap } from "rxjs/operators";
import { Injectable } from "@angular/core";
import { HttpClient, HttpErrorResponse } from "@angular/common/http";
import { catchError } from "rxjs/operators";
import { throwError, Subject } from "rxjs";
import { User } from "./user.model";

export interface AuthResponseData {
  idToken: string;
  email: string;
  refreshToken: string;
  expiresIn: string;
  localId: string;
  registered?: boolean;
}

@Injectable({ providedIn: "root" })
export class AuthService {
  user = new Subject<User>();

  constructor(private http: HttpClient) {}

  signup(email: string, password: string) {
    return this.http
      .post<AuthResponseData>(
        "https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=AIzaSyCXKvAogUtEvySFdP1rIiJgTriL0QFeUP4",
        {
          email: email,
          password: password,
          returnSecureToken: true,
        }
      )
      .pipe(
        catchError(this.handleError),
        tap((resData) => {
          this.handleAuthentication(
            resData.email,
            resData.localId,
            resData.idToken,
            +resData.expiresIn
          );
        })
      );
  }
  login(email: string, password: string) {
    return this.http
      .post<AuthResponseData>(
        "https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=AIzaSyCXKvAogUtEvySFdP1rIiJgTriL0QFeUP4",
        {
          email: email,
          password: password,
          returnSecureToken: true,
        }
      )
      .pipe(catchError(this.handleError), tap((resData) => {
        this.handleAuthentication(
          resData.email,
          resData.localId,
          resData.idToken,
          +resData.expiresIn
        );
      }));
  }

  private handleAuthentication(
    email: string,
    userId: string,
    token: string,
    expiresIn: number
  ) {
    const expirationDate = new Date(new Date().getTime() + expiresIn * 1000);
    const user = new User(email, userId, token, expirationDate);
    this.user.next(user);
  }

  private handleError(errorRes: HttpErrorResponse) {
    let errorMessage = "An error occurred";
    if (!errorRes.error || !errorRes.error.error) {
      return throwError(errorMessage);
    }
    switch (errorRes.error.error.message) {
      case "EMAIL_EXISTS":
        errorMessage = "This email already exists!";
        break;
      case "EMAIL_NOT_FOUND":
        errorMessage = "This email does not exist!";
        break;
      case "INVALID_PASSWORD":
        errorMessage = "This password is wrong!";
        break;
    }
    return throwError(errorMessage);
  }
}

这是组件:

import { Router } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService, AuthResponseData } from './auth.service';
import { NgForm } from '@angular/forms';
import { Component } from '@angular/core';

@Component({
  selector: 'app-auth',
  templateUrl: './auth.component.html',
})
export class AuthComponent {
  isLoginMode = true;
  isLoading = false;
  error: string = null;

  constructor(private authService: AuthService, private router: Router) {}

  onSwitchMode() {
    this.isLoginMode = !this.isLoginMode;
  }
  onSubmit(form: NgForm) {
    if (!form.valid) {
      return;
    }
    console.log(form.value);

    const email = form.value.email;
    const password = form.value.password;

    let authObs: Observable<AuthResponseData>;

    this.isLoading = true;
    if (this.isLoginMode) {
     authObs = this.authService.login(email, password);
    } else {
     authObs = this.authService.signup(email, password);
    }
    authObs.subscribe(
      resData => {
        console.log(resData);
        this.isLoading = false;
        this.router.navigate(['/decks']); 
      },
      errorMessage => {
        console.log(errorMessage);
        this.error = errorMessage;
        this.isLoading = false;
      }
    );

    form.reset();
  }
}

注册工作正常,并且我在Firebase中看到注册用户,但是当我尝试登录时得到以下响应:

{kind: "identitytoolkit#VerifyPasswordResponse", localId: "502dZv8GZzNCpPx2p1XM5DKmpv62", email: "test@test.com", displayName: "", idToken: "eyJhbGciOiJSUz...iIsImtpZCI6ImY1YzlhZWJlMjM0ZGE2MD…gQ0X6EUKKmv0fB8fzXBRQQMrNY0cgHj0hEWRn1PvtLGxGPx-A", …}
displayName: ""
email: "test@test.com"
expiresIn: "3600"
idToken: "eyJhbGciOiJSUzI1NiIsImtpZCI6ImY1YzlhZWJlMjM0ZGE2MDE2YmQ3Yjk0OTE2OGI4Y2Q1YjRlYzllZWIiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vYW5nLWNhcmRzIiwiYXVkIjoiYW5nLWNhcmRzIiwiYXV0aF90aW1lIjoxNTkwMDYzNTQ5LCJ1c2VyX2lkIjoiNTAyZFEdaek5DcFB4MnAxWE01REttcHY2MiIsInN1YiI6IjUwMmRadjhHWnpOQ3BQeDJwMVhNNURLbXB2NjIiLCJpYXQiOjE1OTAwNDksImV4cCI6MTU5MDA2NzE0OSwiZW1haWwiOiJ0ZXN0QHRlc3QuY29tIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJmaXJlYmFzZSI6eyJpGl0aWVzIjp7ImVtYWlsIjpbInRlc3RAdGVzdC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJwYXNzd29yZCJ9fQ.DoP2FeIlP4Q4aIjWbBs_Z8Jo--ptuvEoj7Uy1qbUNDUr1VFkUlq-iddAnEu3knIGc8QpexoUPgBwvMrXljJDgExFm0AwLVLo23nn6OAAXOXAPrrNaFcRQgfuIu0rjtOzH6W-_Ne4e2THEd1NqWkrfsixk6WwAsYMAVVMk...OEERbCwfMZV5a7Y7RoNsJydMFGFghOBtZI0-BWyqgZJr_HyrAZxzdpCPzAhcN6WYfk-EK9vRWXM4kjWulpAyvJcoD_XNR_wbKkog9FXRX3pONELvBPM9oMnMaOZdu6udgQ0X6EUKKmv0fB8fzXBRQQMrNY0cgHj0hEWRn1PvtLGxGPx-A"
kind: "identitytoolkit#VerifyPasswordResponse"
localId: "502dZv8GZz...NCpp1XM5DKmpv62"
refreshToken: "AE0u-NcG9G0W7y75-9s9iFXGs..aODsE04Kc4lfbQR2stlB_E3KsJkS0XGB-lDQ-edFBDOFAeozebNlPCw7wGvGxZK2vXdqvHj8LnNjFAVzS9Zf5FW32irgXHn9y1Cdsb9_ww0piwqgxcPaWLo7UhiWGC0YL8jKtFSmfbLctez9RI-C4OVB0m3WC9W4USFlWxBToEhY3"
registered: true

和此错误:

HttpErrorResponse {headers: HttpHeaders, status: 401, statusText: "Unauthorized", url: "https://ang-cards.firebaseio.com/decks.json", ok: false, …}
error: {error: "Permission denied"}
headers: HttpHeaders
lazyInit: () => {…}
lazyUpdate: null
normalizedNames: Map(0) {}
__proto__: Object
message: "Http failure response for https://ang-cards.firebaseio.com/decks.json: 401 Unauthorized"
name: "HttpErrorResponse"
ok: false
status: 401
statusText: "Unauthorized"
url: "https://ang-cards.firebaseio.com/decks.json"

为什么我会收到“权限被拒绝”的信息? 我在做什么错了?

这是在其中导航的卡片组列表组件的初始化

  ngOnInit() {
    this.decks = this.deckService.getDecks();
    this.dataStorageService.fetchDecks();
    this.deckService.decksChanged.subscribe((decks: Deck[]) => {
      this.decks = decks;
      this.dataStorageService.storeDecks();
    });
  }

1 个答案:

答案 0 :(得分:0)

我刚刚意识到我忘了攻击获取请求的令牌,我想这是问题所在