title: Login from Android application to a Silex REST API
body: <p>I developed an API in PHP using Silex, and i would like to be able to access it from an Android application and a website. I already developed the website, who is able to access the API perfectly.</p>
  
  <p>I tried to do the same with my Android application but it's not working. The problem i have is i don't really understand how can i log myself as a user, using the same method i used for the website. I use the SecurityServiceProvider from Silex to handle the login and token part, which is working on my website.</p>
  
  <p>Here are the codes :</p>
  
  <p>SecurityServiceProvider in app.php :</p>
  
  <pre><code>    $app-&gt;register(new Silex\Provider\SecurityServiceProvider(), array(
          'security.firewalls' =&gt; array(
      'login' =&gt; array(
          'pattern' =&gt; '^/login$',
      ),
      'secured' =&gt; array(
          'pattern' =&gt; '^/',
          'form' =&gt; array('login_path' =&gt; '/login', 'check_path' =&gt; '/login_check'),
          'logout' =&gt; array('logout_path' =&gt; '/logout'),
          'users' =&gt; function($app) {
          return new App\User\Provider\UserProvider($app['db']);
          }),
      ),
  
  
      'security.role_hierarchy' =&gt; array(
          'ROLE_USER' =&gt; array(),
          'ROLE_ADMIN' =&gt; array('ROLE_USER'),
      ),
  
  'security.access_rules' =&gt; array(
  
      array('^/user', 'ROLE_USER'),
      array('^/admin', 'ROLE_ADMIN'),
  )
  ));
  </code></pre>
  
  <p>Login part in login.html.twig call with /login:</p>
  
  <pre><code>&lt;form class="form-horizontal" role="form" method="post" action="{{ path('login_check') }}"&gt;
      &lt;div class="form-group"&gt;
          &lt;label for="inputEmail1" class="col-lg-2 col-sm-2 control-label"&gt;Login&lt;/label&gt;
          &lt;div class="col-lg-10"&gt;
              &lt;input type="text" class="form-control" id="login" name="_username" placeholder="Login"&gt;
          &lt;/div&gt;
      &lt;/div&gt;
      &lt;div class="form-group"&gt;
          &lt;label for="inputPassword1" class="col-lg-2 col-sm-2 control-label"&gt;Mot de Passe&lt;/label&gt;
          &lt;div class="col-lg-10"&gt;
              &lt;input type="password" class="form-control" id="mdp" name="_password" placeholder="Mot de Passe"&gt;
          &lt;/div&gt;
      &lt;/div&gt;
      &lt;div class="form-group"&gt;
          &lt;div class="col-lg-offset-2 col-lg-10"&gt;
              &lt;div class="checkbox"&gt;
                  &lt;label&gt;
                      &lt;input type="checkbox"&gt; Se Souvenir de Moi
                  &lt;/label&gt;
              &lt;/div&gt;
          &lt;/div&gt;
      &lt;/div&gt;
      &lt;div class="form-group"&gt;
          &lt;div class="col-lg-offset-2 col-lg-10"&gt;
              &lt;button type="submit" class="btn btn-danger"&gt;Connexion&lt;/button&gt;
          &lt;/div&gt;
      &lt;/div&gt;
  &lt;/form&gt;
  </code></pre>
  
  <p>LoginActivity in Android :</p>
  
  <pre><code>public class LoginActivity extends AppCompatActivity {
      private static final String TAG = "LoginActivity";
      private static final int REQUEST_SIGNUP = 0;
  
      @Bind(R.id._username) EditText username;
      @Bind(R.id._password) EditText password;
      @Bind(R.id.btn_login) Button _loginButton;
      @Bind(R.id.link_signup) TextView _signupLink;
  
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_login);
          ButterKnife.bind(this);
  
          _loginButton.setOnClickListener(new View.OnClickListener() {
  
              @Override
              public void onClick(View v) {
                  login();
              }
          });
  
          _signupLink.setOnClickListener(new View.OnClickListener() {
  
              @Override
              public void onClick(View v) {
                  // Start the Signup activity
                  Intent intent = new Intent(getApplicationContext(), SignupActivity.class);
                  startActivityForResult(intent, REQUEST_SIGNUP);
                  finish();
                  overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out);
              }
          });
      }
  
      public void login() {
  
          if (!validate()) {
              onLoginFailed();
              return;
          }
  
          _loginButton.setEnabled(false);
  
          final ProgressDialog progressDialog = new ProgressDialog(LoginActivity.this,
                  R.style.AppTheme_Dark_Dialog);
          progressDialog.setIndeterminate(true);
          progressDialog.setMessage("Authenticating...");
          progressDialog.show();
  
          String _username = username.getText().toString();
          String _password = password.getText().toString();
  
          Call&lt;User&gt; userCall = APIClient.getApiInterface().getUser(_username, _password);
          userCall.enqueue(new Callback&lt;User&gt;() {
              @Override
              public void onResponse(Call&lt;User&gt; call, Response&lt;User&gt; response) {
                  if (response.body() == null) {
  
                      // Toast
                  } else
                  {
  
                  }
              }
  
              @Override
              public void onFailure(Call&lt;User&gt; call, Throwable t) {
                  Log.d("Going here", "Don't know why");
              }
          });
          // TODO: Implement your own authentication logic here.
  
          new android.os.Handler().postDelayed(
                  new Runnable() {
                      public void run() {
                          // On complete call either onLoginSuccess or onLoginFailed
                          onLoginSuccess();
                          // onLoginFailed();
                          progressDialog.dismiss();
                      }
                  }, 3000);
      }
  
  
      @Override
      protected void onActivityResult(int requestCode, int resultCode, Intent data) {
          if (requestCode == REQUEST_SIGNUP) {
              if (resultCode == RESULT_OK) {
  
                  // TODO: Implement successful signup logic here
                  // By default we just finish the Activity and log them in automatically
                  this.finish();
              }
          }
      }
  
      @Override
      public void onBackPressed() {
          // Disable going back to the MainActivity
          moveTaskToBack(true);
      }
  
      public void onLoginSuccess() {
          _loginButton.setEnabled(true);
          finish();
      }
  
      public void onLoginFailed() {
          Toast.makeText(getBaseContext(), "Login failed", Toast.LENGTH_LONG).show();
  
          _loginButton.setEnabled(true);
      }
  
      public boolean validate() {
          boolean valid = true;
  
          String _username = username.getText().toString();
          String _password = password.getText().toString();
  
          if (_username.isEmpty()) {
              username.setError("enter a valid email address");
              Log.d(TAG, "Login");
              valid = false;
          } else {
              username.setError(null);
          }
  
          if (_password.isEmpty() || _password.length() &lt; 4) {
              password.setError("between 4 and 10 alphanumeric characters");
              valid = false;
          } else {
              password.setError(null);
          }
  
          return valid;
      }
  }
  </code></pre>
  
  <p>APIClient in Android :</p>
  
  <pre><code>public class APIClient {
  
      public static final String BASE_URL = "http://localhost:8080/";
      private static Retrofit retrofit = null;
  
      public static Retrofit getClient() {
          if (retrofit == null) {
              retrofit = new Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create()).build();
          }
          return retrofit;
      }
  
      public static APIInterface getApiInterface() {
          APIInterface apiService = APIClient.getClient().create(APIInterface.class);
          return apiService;
      }
  
  
  }
  </code></pre>
  
  <p>APIInterface in Android :</p>
  
  <pre><code>public interface APIInterface {
  
      @FormUrlEncoded
      @POST("login")
      Call&lt;User&gt; getUser(@Field("_username") String _username, @Field("_password") String _password);
  
  }
  </code></pre>
  
  <p>So technically i thought sending a form with the fields "_username" and "_password" would do it, but apparently it doesn't.</p>
  
  <p>It's just been a few months since i started studying and working in all mobile/webservice/web environment so i'm not very familiar with everything. Also let me know if you need more informations about the code, or if there is better way to do it.</p>