PHPでログイン用APIの作成


PHPでユーザログインのAPIを作成しています。以下のコードを作成し、クライントサイドからメールアドレスとパスワードをPOSTしたのですが、401エラーで正しく認証できませんでした。  
ユーザデータはデータベースにあるのでメールアドレスとパスワードの打ち間違いはありません。どこを間違えているかわかりますか。またデバッグ方法などありましたら教えて下さい。よろしくお願いします。

**ソーズコード**

[code]

      1 <?php
      2 header("Content-Type: application/json; charset=UTF-8");
      3 header("X-Content-Type-Option: nosniff");
      4 header("Access-Control-Allow-Origin: *");
      5 header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept");
      6 require_once 'functions.php'
      7 $pdo = initDB()
      8 switch($_SERVER['REQUEST_METHOD']){
      9 case 'POST':
     10   $in = json_decode(file_get_contents('php://input'), true);
     11   if(isset($in['mail_address'])&&isset($in['password'])){
     12     $st = $pdo->prepare("SELECT * FROM user WHERE (mail_address) VALUE (:mail_address)");
     13     $st->bindParam(':mail_address', $in['mail_address'], PDO::PARAM_STR);
     14     $st->execute();
     15     while($row = $st->fetch(PDO::FETCH_ASSOC)){
     16       $password = $row['password'];
     17     }
     18     if($password==$in['password']){
     19       onPostSuccess($in['mail_address']);
     20     }else{
     21       header("HTTP/1.0 401 Unauthorixed");
     22     }
     23   }else{
     24     header("HTTP/1.0 400 Bad Request");
     25   }
     26 }
     27
     28 function onPostSuccess($mailAddress){
     29   $accessToken = makeAccessToken();
     30   $st = $pdo->prepare("UPDATE user SET accessToken=:accessToken WHERE mail_address=:mail_address");
     31   $st->bindParam(':accessToken', $accessToken, PDO::PARAM_STR);
     32   $st->bindParam(':mail_address', $mailAddress, PDO::PARAM_STR);
     33   $st->execute();
     34   header("HTTP/1.0 200 OK");
     35   echo json_encode(array('accessToken' => $accessToken));
     36 }
    
[/code]




最終的に以下のようになりました。回答をしてくださった方々に感謝します。パスワードのセキュリティの問題など勉強になりました。パスワードをハッシュ化して保存したり、サードパーティの認証ライブラリの使用も検討したいと思います。

[code]

    <?php
    header("Content-Type: application/json; charset=UTF-8");
    header("X-Content-Type-Option: nosniff");
    header("Access-Control-Allow-Origin: *");
    header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept");
    require_once 'functions.php';
    $pdo = initDB();
    switch($_SERVER['REQUEST_METHOD']){
    case 'POST':
      $in = json_decode(file_get_contents('php://input'), true);
      $error = '';
      if(isset($in['mail_address'])&&isset($in['password'])){
        $st = $pdo->prepare("SELECT * FROM user WHERE mail_address=:mail_address");
        $st->bindParam(':mail_address', $in['mail_address'], PDO::PARAM_STR);
        $st->execute();
        $row = $st->fetch(PDO::FETCH_ASSOC);
        $password = $row['password'];
        if($password!=null){
          if($password==$in['password']){
            onPostSuccess($pdo, $in['mail_address']);
          }else{
            header("HTTP/1.0 401 Unauthorixed");
            $error = "パスワードが違います。";
            sendError($error);
          } 
        }else{
          header("HTTP/1.0 401 Unauthorixed");
          $error = "メールアドレスが登録されていません。";
          sendError($error);
        }
      }else{
        header("HTTP/1.0 400 Bad Request");
      }
      break;
    }
    
    function onPostSuccess($pdo, $mailAddress){
      $accessToken = makeAccessToken();
      $st1 = $pdo->prepare("UPDATE user SET accessToken=:accessToken WHERE mail_address=:mail_address");
      $st1->bindParam(':accessToken', $accessToken, PDO::PARAM_STR);
      $st1->bindParam(':mail_address', $mailAddress, PDO::PARAM_STR);
      $st1->execute();
      header("HTTP/1.0 200 OK");
      echo json_encode(array('accessToken' => $accessToken));
    }
    
[/code]




パスワードが生で保存されているっぽいのは、おいといて。

個人的には、このコードから見て考えつくのは  
同一メールアドレスのパスワード違いが複数行あって、  
`while($row = $st->fetch(PDO::FETCH_ASSOC)){}`  
のところでorderもかかっていない最終行のパスワードの何かが  
入力されたものと一致していない可能性がある。というところが疑わしいです。

それから「401 Unauthorixed」(Unauthorixed...?)が発生するのは、  
if($password==$in['password'])のでの判定だけですよね。  
この直前で両方の変数を、出力でもして確認するのが最適だと思います。

……ところで気になったのですが。  
DBへの問い合わせクエリの中で、メールアドレスとパスワードの両方を渡せばいいのでは？  
なぜwhileで回しているのでしょうか。

