-1

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.

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.

Here are the codes :

SecurityServiceProvider in app.php :

    $app->register(new Silex\Provider\SecurityServiceProvider(), array(
        'security.firewalls' => array(
    'login' => array(
        'pattern' => '^/login$',
    ),
    'secured' => array(
        'pattern' => '^/',
        'form' => array('login_path' => '/login', 'check_path' => '/login_check'),
        'logout' => array('logout_path' => '/logout'),
        'users' => function($app) {
        return new App\User\Provider\UserProvider($app['db']);
        }),
    ),


    'security.role_hierarchy' => array(
        'ROLE_USER' => array(),
        'ROLE_ADMIN' => array('ROLE_USER'),
    ),

'security.access_rules' => array(

    array('^/user', 'ROLE_USER'),
    array('^/admin', 'ROLE_ADMIN'),
)
));

Login part in login.html.twig call with /login:

<form class="form-horizontal" role="form" method="post" action="{{ path('login_check') }}">
    <div class="form-group">
        <label for="inputEmail1" class="col-lg-2 col-sm-2 control-label">Login</label>
        <div class="col-lg-10">
            <input type="text" class="form-control" id="login" name="_username" placeholder="Login">
        </div>
    </div>
    <div class="form-group">
        <label for="inputPassword1" class="col-lg-2 col-sm-2 control-label">Mot de Passe</label>
        <div class="col-lg-10">
            <input type="password" class="form-control" id="mdp" name="_password" placeholder="Mot de Passe">
        </div>
    </div>
    <div class="form-group">
        <div class="col-lg-offset-2 col-lg-10">
            <div class="checkbox">
                <label>
                    <input type="checkbox"> Se Souvenir de Moi
                </label>
            </div>
        </div>
    </div>
    <div class="form-group">
        <div class="col-lg-offset-2 col-lg-10">
            <button type="submit" class="btn btn-danger">Connexion</button>
        </div>
    </div>
</form>

LoginActivity in Android :

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<User> userCall = APIClient.getApiInterface().getUser(_username, _password);
        userCall.enqueue(new Callback<User>() {
            @Override
            public void onResponse(Call<User> call, Response<User> response) {
                if (response.body() == null) {

                    // Toast
                } else
                {

                }
            }

            @Override
            public void onFailure(Call<User> 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() < 4) {
            password.setError("between 4 and 10 alphanumeric characters");
            valid = false;
        } else {
            password.setError(null);
        }

        return valid;
    }
}

APIClient in Android :

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;
    }


}

APIInterface in Android :

public interface APIInterface {

    @FormUrlEncoded
    @POST("login")
    Call<User> getUser(@Field("_username") String _username, @Field("_password") String _password);

}

So technically i thought sending a form with the fields "_username" and "_password" would do it, but apparently it doesn't.

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.

Robin TL
  • 1
  • 2

1 Answers1

-1

Hi there i think you are looking for Silex guard_authentication:

Suppose you have an API where your clients will send an X-AUTH-TOKEN header on each request. This token is composed of the username followed by a password, separated by a colon (e.g. X-AUTH-TOKEN: coolguy:awesomepassword). Your job is to read this, find the associated user (if any) and check the password.

*Update:

Check this: https://stackoverflow.com/a/21600804/4270737

https://silex.sensiolabs.org/index.php/doc/2.0/cookbook/guard_authentication.html

Community
  • 1
  • 1
Slico
  • 436
  • 2
  • 16
  • I actually didn't downvote, i don't know who did :/ i'll check what you sent me asap, thanks for answering ! – Robin TL Apr 19 '17 at 09:07
  • Don't worry for the down vote, i'm curious why the down vote because maybe i'm not correct. Was it useful the info provided? – Slico Apr 20 '17 at 08:51