Why session PHP can't be used with Ionic?

Hello,

I’m not sure about how securise the communication between app client (ionic android) and app server (php).

Have I need to pass the user id + the token at each request et verify the validity at each request between client/server or it exists an other method ?

I try to use $_SESSION with php but it seem ionic can’t work with php sessions.

Any help please ?
Thanks very much,

JWT is the canonical answer to this today.

1 Like

Hello,

Thanks for your answer !

With PostMan I can :

  • call url “/authenticate” to get a token
  • call the api “/api/users/me” to get the profil of user loged (with {headers: { “Authorization”: “Bearer <the token>” }})

When I try with ionic I have a error.
Here my method :

  toGetProfil() {
    return new Promise((resolve, reject) => {
      let options = new RequestOptions({
        headers: new Headers({
          'Authorization': 'Bearer ' + localStorage.getItem('token')
        })
      })
      this.http.get(this.api + '/users/me', options)
        .map(res => res.json())
        .catch(err => {
          reject(err)
          return Observable.throw("it seem this throw is useless")
        })
        .subscribe(
          res => resolve(res)),
          err => reject(err)
    })
  }

The error :

  {
    "_body": {
      "isTrusted": true
    },
    "status": 0,
    "ok": false,
    "statusText": "",
    "headers": {},
    "type": 3,
    "url": null
  }

I try to debug this since many hours without any results.
Have you an idea please ?

Thank you,

Solved !

This code was good from the begins:

  constructor(private http: Http)
  {
    this.options = new RequestOptions({
      headers: new Headers({
        'Authorization': 'Bearer ' + localStorage.getItem('token')
      })
    })
  }

  toGetProfil() {
    return new Promise((resolve, reject) => {
      this.http.get(this.api + '/users/me', this.options)
        .map(res => res.json())
        .catch(err => {
          reject(err)
          return Observable.throw("it seem this throw is useless")
        })
        .subscribe(res => resolve(res))
    })
  }

The prob was server side : (I need to add “authorization” as allowed headers and add “secure => false” for JwtAuthentication)

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");
header("Access-Control-Allow-Headers: content-type, authorization");

$app = new \Slim\App([
  'settings' => [
    'displayErrorDetails' => true,
  ],
]);

$app->add(new \Slim\Middleware\JwtAuthentication([
  "secure"      => false,
  "secret"      => "blablabla",
  "path"        => "/api",
  "algorithm"   => ["HS256"]
]));
1 Like

You shouldn’t be explicitly instantiating a Promise. Just return the Observable that Http gives you, and call toPromise() on it if you must.

Hey, Thats a good solution but token never will change and someone who need to get token. He just need to find your “/authenticate” page. Here is my solution.

getIp.php —> return user ip adress as a json format
ionicApp ----> send request getIp.php, use md5 with secret key + userip send request to server with your key
register.php ----> get request, create your token with php (same secret key) and if not equal return bad request

and obfuscate your ionic page

No. Don’t attempt to roll your own homebrew security protocols, period, and don’t use md5 for anything.

Can I ask, why we don’t ?

Anyone, from the most clueless amateur to the best cryptographer, can create an algorithm that he himself can’t break. It’s not even hard. What is hard is creating an algorithm that no one else can break, even after years of analysis. And the only way to prove that is to subject the algorithm to years of analysis by the best cryptographers around.

That’s Bruce Schneier.

JWT has been subject to that level of public analysis for years. Use it.

Your proposed protocol has a myriad of easily exploitable holes as well as lack of features. Aside from using a known broken hash function in MD5, it relies on embedding a secret in the app binary. That’s impossible. Anybody with a copy of the app binary knows the secret key. No amount of “obfuscation” can get around that. You can’t expire tokens. Probably most problematically, it doesn’t even prove that anybody knows anything or has anything (except for a copy of the app binary, which means nothing).

1 Like

Thanks for great answer. I am new here and I need to learn a lots of stuff. When I research JWT, I understand why we don’t use own protocol.

Thanks rapropos, it’s more clean with toPromise :

  toAuthenticate(accessToken) {
    return this.http.get(this.url + '/authenticate/' + accessToken)
      .map(res => res.json())
      .catch(err => { this.toast.push(err); return Observable.throw(err) })
      .toPromise()
  }

Hi @reliy0n,

My PHP authenticate route recieve the accessToken Facebook

PHP verify with fb api if the accessToken is valid and then generate the JWT.

To obtain a JWT, the malicious poeple have to pass a valid accessToken (validated by facebook api)

My complete code :

header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");
header("Access-Control-Allow-Headers: content-type, authorization");

// Authentification
$app->get('/authenticate/{accessToken}', function (Request $request, Response $response) use ($em, $fb) {

  // Le client a obtenu un Token Facebook qu'il envoie à php
  $accessToken = $request->getAttribute('accessToken');

  // On vérifie que le token est valide et on récupère le profil incluant l'idFacebook
  $graph = $fb->get('/me?fields=id,name,email,picture', $accessToken)->getGraphNode()->asArray();

  // On met à jour et récupère le user en db (incluant lastConnexion) sur base de son idFacebook
  $user = User::updateFromGraph($graph, $em);

  // On génère un token contenant le user_id de la table User
  $token = toGenerateToken($user->getId());

  return $response->withJson(["token" => $token]);

});

 function toGenerateToken($uid) {
  $header = base64url_encode(json_encode([
    "alg" => "HS256",
    "typ" => "JWT"
  ]));

  $payload = base64url_encode(json_encode([
    "uid"         => $uid
  ]));

  $signature = base64url_encode(hash_hmac('SHA256', $header . "." . $payload, JWT_SECRET, true));

  return "$header.$payload.$signature";
}

I was able to use $_SESSION with ionic-angular-3.9.2 with the answer shown here: Setting request cookies angular2 http post request

Not 100% sure these headers are necessary, but I added them to my PHP:
header(‘Access-Control-Allow-Origin: http://localhost:8080’);
header(‘Access-Control-Allow-Credentials: true’);
header(“Access-Control-Allow-Methods:POST,GET,OPTIONS”);
More details are available here: Cross-Origin Research Sharing (CORS)