Skip to content
This repository has been archived by the owner on Apr 17, 2023. It is now read-only.

AGDROID-686 Token integrity check #21

Merged
merged 17 commits into from
Feb 8, 2018
Merged

Conversation

aidenkeating
Copy link
Contributor

@aidenkeating aidenkeating commented Jan 31, 2018

Motivation

JIRA: https://issues.jboss.org/browse/AGDROID-686

Description

Function to Verify JWT Tokens (Access, Identity, Refresh) using a Keycloak Realm Public Key before they are used as part of client side access control decisions.

Provide the configuration from the JSON mobile configuration to the OIDCCredentials.

Tested successfully with both valid & tampered Access/Identity tokens. Identity Brokering originated tokens can also be validated.

Progress

  • Get the Public Key from the Mobile Core Config (when available)
  • Get the Audience from the Mobile Core Config (when available)
  • Construct the integrity parameters (build issuer etc.) from the core config.
  • Add Unit tests - Test Wrong issues, audiences, tampered signature, payload, algorithm info sections etc

@aidenkeating
Copy link
Contributor Author

@ziccardi @secondsun Would you mind taking a look?

This adds IntegrityCheckParameters that are part of the OIDCCredentials containing the issuer, audience and publicKey from the mobile JSON config.

At the moment it looks like the SDK user would provide the credential at login. In this case I'm kind of confused as at the moment Credential seems to be used as a container for the tokens when a user has already authenticated. I don't understand why/how a user would provide that information at login.

Something tells me OIDCCredential has become more like AuthState and OIDCCredentials should be refactored to OIDCAuthState. Something that is created once a user is logged in instead of something the SDK user provides.

A call may be better to explain this.

@ziccardi
Copy link
Member

@aidenkeating The authentication is performed through the usage of an authentication chain that can be configured at runtime.
Some of the rings of the authentication chain require a credential to be supplied (for example, to check that the token is still valid), some of them do not require the credentials (for example the browser authentication).
In both cases, after the user has been authenticated, an UserPrincipal object is returned containing the UserCredentials (in case of OIDC, it will contain the auth tokens).

public AbstractAuthenticator(final AuthServiceConfig config) {
this.config = config;

public AbstractAuthenticator(ServiceConfiguration serviceConfig) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make the parameter final

private AuthService(final AuthServiceConfig config) {
public AuthService() {}

public void bootstrap(MobileCore core, ServiceConfiguration serviceConfig) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make the params final

.toString();
}

public static IntegrityCheckParameters deserialize(String serializedParams) throws JSONException {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make the param final

private String audience;
private String publicKey;

public IntegrityCheckParameters(String audience, String issuer, String publicKey) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make the params final

* @param jwtToken The JWT token to verify.
* @return <code>true</code> if the token integrity is good.
*/
public boolean verifyToken(String jwtToken) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make the param final

* @param audience - The expected Audience of the JWT
* @return <code>true</code> if the token integrity is good.
*/
public boolean verifyToken(String jwtToken, String publicKey, String issuer, String audience) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See previous comments

// Validate the JWT and process it to the Claims
JwtClaims jwtClaims = jwtConsumer.processToClaims(jwtToken);
verified = true;
System.out.println("JWT Verified Successfully.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't use System.out

catch (InvalidJwtException e)
{
// InvalidJwtException will be thrown, if the JWT failed processing or validation in anyway.
System.out.println("JWT Validation Failed. " + e.getLocalizedMessage());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See previous comment

.toString();
}

public static OIDCCredentials deserialize(String serializedCredential) throws JSONException {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make parameter final

public String serialize() throws JSONException {
return new JSONObject()
.put("authState", this.authState.jsonSerializeString())
.put("integrityCheck", this.integrityCheckParameters.serialize())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

integrityCheckParameters could be null

@secondsun
Copy link
Contributor

@aidenkeating Do you have a demo project that shows the code being used somewhere?

@aidenkeating
Copy link
Contributor Author

@secondsun Not yet. I can implement it in https://github.com/feedhenry/mobile-security-android-template

Copy link
Contributor

@secondsun secondsun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aidenkeating Mostly looks good, added a few changes. The most important one I think is changing the JSON exception to a more descriptive run time exception.

The general argument is that we aren't working on JSON at a conceptual level. We are using OIDC tokens and configurations instead. This means that JSONException is leaking internal information that is not relevant to the user's tasks. Because this information isn't relevant we end up with exceptions that aren't solvable by the user (see here throws JSONException being leaked everywhere)

targetCompatibility = "1.7"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove these two lines, they are already set above to 1.8

@@ -1,6 +1,7 @@
package org.aerogear.auth;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@secondsun : just to be sure, should we rename it to org.aerogear.android.ags.auth?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ziccardi Yes

public boolean verifyToken(final String jwtToken, final String publicKey, final String issuer, final String audience) {
// add the Begin/End tags to the public key generated from Keycloak
String beginPublicKey = "-----BEGIN PUBLIC KEY-----";
String endPublicKey = "-----END PUBLIC KEY-----";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these should be private static final constant fields instead of local variables.

JwtClaims jwtClaims = jwtConsumer.processToClaims(jwtToken);
return true;
} catch (InvalidJwtException e) {
e.printStackTrace();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now use Android's Log object instead of printing the stack trace.

@@ -67,8 +145,21 @@ public boolean isAuthorized() {
* Returns stringified JSON for the OIDCCredential.
* @return Stringified JSON OIDCCredential
*/
public String serialise() {
return this.authState.jsonSerializeString();
public String serialize() throws JSONException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is serialize used?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally I would remove the JSONException from the method declaration and rethrow it as a runtime exception and add that clue to the documentation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@secondsun serialize is used when persisting the auth state in the AuthStateManager.

return jsonCredential.toString();
}

public static OIDCCredentials deserialize(final String serializedCredential) throws JSONException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above comments about JSONException.

@@ -39,11 +39,11 @@ public OIDCCredentials read() {
* Saves a token
* @param authState token to be saved
*/
public synchronized void write(final OIDCCredentials authState) {
public synchronized void write(final OIDCCredentials authState) throws JSONException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like the name "write". I think save is more descriptive. Also if we wrap the JSONExceptions above we aren't "leaking" it here.

OIDCCredentials oidcCredentials = new OIDCCredentials();
assertFalse("Expect Token Validation with Tampered Refresh Token to Fail", oidcCredentials.verifyToken(TAMPERED_REFRESH_TOKEN, VALID_PUBLIC_KEY, VALID_ISSUER, VALID_AUDIENCE));
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could the repeated "OIDCCredentials oidcCredentials = new OIDCCredentials();" be in the setup block?

private AuthService(final AuthServiceConfig config) {
public AuthService() {}

public void bootstrap(final MobileCore core, final ServiceConfiguration serviceConfig) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When is the bootstrap called?
If we don't initialise the object inside the constructor, we should than throw an IllegalStateException if other methods are called before the bootstrap one.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@secondsun Am I correct in saying the core will initialize and then call bootstrap on a ServiceModule?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


public IntegrityCheckParameters() {}

public String getIssuer() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add some documentation here. What is the issuer?

return this.audience;
}

public String getPublicKey() { return this.publicKey; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this public key? What is the format it is returned? It is a DSA? RSA? or what?

.toString();
}

public static IntegrityCheckParameters deserialize(final String serializedParams) throws JSONException {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this object supposed to be constructed only through this method? If yes, the constructor should be private

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No this will need to be constructed through the constructor when initially created at authentication time.

.toString();
}

public static IntegrityCheckParameters deserialize(final String serializedParams) throws JSONException {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A null check should be added here

.setRequireSubject() // require the subject claim
.setExpectedIssuer(issuer) // whom the JWT needs to have been issued by
.setExpectedAudience(audience) // to whom the JWT is intended for
.setVerificationKey(jwtPublicKey) // verify the signature with the public key
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it ok to have a null jwtPublicKey here? If it is not, make it final and do not assign null to it.

final PublicKey jwtPublicKey;
try {
    jwtPublicKey = utils.fromPemEncoded(constructedPublicKey);
} catch (JoseException e) {

JwtClaims jwtClaims = jwtConsumer.processToClaims(jwtToken);
return true;
} catch (InvalidJwtException e) {
e.printStackTrace();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we can safely return false here, it would be better to use logger to log exceptions.

public String serialise() {
return this.authState.jsonSerializeString();
public String serialize() throws JSONException {
JSONObject jsonCredential = new JSONObject()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every time a variable is not supposed to be assigned again, it should be declared as final.

return jsonCredential.toString();
}

public static OIDCCredentials deserialize(final String serializedCredential) throws JSONException {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this object is supposed to be created only through this method, the constructor should be private.

if (authState == null) {
clear();
} else {
if(!prefs.edit().putString(KEY_STATE, authState.serialise()).commit()) {
if(!prefs.edit().putString(KEY_STATE, authState.serialize()).commit()) {
throw new IllegalStateException("Failed to update state from shared preferences");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it correct to throw an unchecked exception here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ziccardi Yes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, we should add @throws to the javadocs

testImplementation 'org.mockito:mockito-core:2.10.0'
testImplementation 'junit:junit:4.12'
testImplementation "org.robolectric:robolectric:3.6.1"
compile 'org.bitbucket.b_c:jose4j:0.6.3'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

compile is deprecated. replace with implementation and move above the test dependencies. Also can you include the dependency in the android bom https://github.com/aerogear/aerogear-parent/blob/master/aerogear-android-sdk-bom/pom.xml, passos is working on moving this to use a more managed system.

@@ -1,6 +1,7 @@
package org.aerogear.auth;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ziccardi Yes

String getIssuer();
String getPublicKey();
boolean isValid();
String serialize() throws JSONException;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nix the exception

*/
public String getPublicKey() { return this.publicKey; }

public String serialize() throws JSONException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code will never throw a JSON exception, best not to declare it.

* Return json representation of the parameters
* @return json string representation of parameters
*/
public static IntegrityCheckParameters deserialize(final String serializedParams) throws JSONException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kill the exception.

If you have to throw a checked exception (pro tip, you don't), make it more specific to the task at hand. For instance if there is no "issuer" property on the object then throwing as JSON exception is less useful than throwing a new IllegalArgumentException with a useful message.

Also, add that the object needs to be a json object with those parameters in the header.

Also also, if all we are doing is storing this in shared preferences can we make it a parcelable instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@secondsun I'm not sure I understand how parcelable would help here?


public OIDCCredentials() {
this.authState = new AuthState();
public OIDCCredentials(final String serialisedCredential, final IIntegrityCheckParameters integrityCheckParameters) throws JSONException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kill the JSONException. Add javadocs.

if (authState == null) {
clear();
} else {
if(!prefs.edit().putString(KEY_STATE, authState.serialise()).commit()) {
if(!prefs.edit().putString(KEY_STATE, authState.serialize()).commit()) {
throw new IllegalStateException("Failed to update state from shared preferences");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, we should add @throws to the javadocs

@aidenkeating
Copy link
Contributor Author

aidenkeating commented Feb 1, 2018

@ziccardi @secondsun Mind taking another look?

protected AuthServiceConfig getConfig() {
return config;
}
public ServiceConfiguration getServiceConfig() { return this.serviceConfig; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is ServiceConfiguration an immutable object?
If it is not, different threads could change the content of the ServiceConfiguration object, thus changing the internal state of the Authenticator without any control by the latter, making it crash prone.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not too familiar with any core stuff. @secondsun would you have an answer to this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ServiceConfiguration is meant to be immutable. If it isn't then feel free to make it so.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have made this change in a separate PR. Don't want this one to bloat much more. https://github.com/aerogear/aerogear-android-sdk/pull/24/files


public class IntegrityCheckParameters implements IIntegrityCheckParameters {

private String issuer;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make these final

* @return <code>true</code> if the token integrity is good.
*/
public boolean verifyToken(final String jwtToken) {
final String issuer = integrityCheckParameters.getIssuer();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no added value in using variables to store the values here.

jwtPublicKey = utils.fromPemEncoded(constructedPublicKey);
} catch (JoseException e) {
Log.e(TAG, e.getMessage(), e);
throw new RuntimeException(e);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use a more specific exception. In this case, if the parameters are not correct, an IllegalArgumentException could be the right one.

}
return jsonCredential.toString();
} catch(JSONException e) {
throw new RuntimeException(e);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See previous comment

final IntegrityCheckParameters icParams = IntegrityCheckParameters.deserialize(serializedIntegrityChecks);
return new OIDCCredentials(serializedAuthState, icParams);
} catch(JSONException e) {
throw new RuntimeException(e);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See previous comment

Copy link
Contributor

@secondsun secondsun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking better, I found a stub method and most of my comments are minor doc and annotation tweaks.

testImplementation 'org.mockito:mockito-core:2.10.0'
testImplementation 'junit:junit:4.12'
testImplementation "org.robolectric:robolectric:3.6.1"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll need to rebase on master and add these dependencies to the aerogear-android-sdk-bom. @danielpassos Can show you how.

protected AuthServiceConfig getConfig() {
return config;
}
public ServiceConfiguration getServiceConfig() { return this.serviceConfig; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ServiceConfiguration is meant to be immutable. If it isn't then feel free to make it so.

String getIssuer();
String getPublicKey();
boolean isValid();
String serialize();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think JavaDocs are needed? The properties and things look self explanatory to me, but if there are any weirdnesses or edge cases to be aware of (like what does isValid check to validate) then I would want them added.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're right about isValid requiring some docs here. For the others I don't think so, they're self explanatory I think.

import org.json.JSONException;
import org.json.JSONObject;

public class IntegrityCheckParameters implements IIntegrityCheckParameters {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the methods you implement you need to add the @Override annotation.


/**
* Return json representation of the parameters
* @return json string representation of parameters
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add @throws to describe why the runtime exception may be thrown.

/**
* Credentials for OIDC based authentication
*/
public class OIDCCredentials implements ICredential {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add @Override where appropriate.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ICredential is just empty at the moment.

* @param serialisedCredential JSON string representation of the authState field produced by
* {@link #deserialize(String)}.
* @param integrityCheckParameters Integrity check parameters for the token.
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add @throws to describe the runtime exception to the javadoc

}
}

public static OIDCCredentials deserialize(final String serializedCredential) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

javadocs.

* @throws AuthenticationException
*/
public boolean renew() throws AuthenticationException {
throw new IllegalStateException("Not yet implemented");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need implementation :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why this is showing up as changed, but the renew was there before this PR and I think it's outside the scope of this PR. I think its implementation is kind of dependent on knowing how login will work.

}

/**
* Saves a token
* @param authState token to be saved
* @throws IllegalArgumentException
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be illegal state exception?

@aidenkeating
Copy link
Contributor Author

@secondsun Dependencies were added in this PR, waiting on a new release now. Have made a temporary commit that will fail so I don't forget

private static final String STORE_NAME = "org.aerogear.android.auth.AuthState";
private static final String KEY_STATE = "state";

private final SharedPreferences prefs;

public AuthStateManager(final Context context) {
private AuthStateManager(final Context context) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if Singleton's are suppose to have parameters? This way couldn't the singleton be instantiated multiple times which defeats the purpose?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Private constructor and prefs is a final variable. IN this case it isn't bad because the references set up aren't mutable. However I am generally -1 to static singletons because they have annoying behaviors when you are testing that you have to code around.

*/
public synchronized void clear() {
if (!prefs.edit().remove(KEY_STATE).commit()) {
throw new IllegalStateException("Failed to clear state from shared preferences");
}
}

public static AuthStateManager getInstance(final Context context) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rachael-oregan To respond to this comment 260a5b3#r166298337 yeah I'm not sure the best way to approach this. I don't think providing a 'setter' of any kind is a good idea as then context could change if the setter is called multiple times. This can't be initialized multiple times but I can see the awkwardness of it.

This way context is bound to whatever is provided first, instead of being able to be set multiple times.

There's also the option of providing context on each function call I guess.

Perhaps @ziccardi or @secondsun have a more informed view on how to approach this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aidenkeating Just a proposal: we could add a bootstrap method with package level visibility. It could then be called from the bootstrap method of the AuthService. This way other classes will see only a getInstance with no parameters. WDYT?

@@ -75,7 +79,7 @@ public void setAuthenticatorChain(AuthenticationChain newChain) {
public static synchronized AuthService getInstance() {
if (INSTANCE == null) {
// FIXME: load the configurations from core and pass it here
INSTANCE = new AuthService(null);
INSTANCE = new AuthService();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should NOT be using singletons. References to services should be fetch through the mobile core and not plucked from the ether.

See https://github.com/aerogear/proposals/blob/master/android-sdk/README.md#referencing-a-service

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I don't think this is used anyway, doesn't seem to be referenced anywhere. Must have been left over. Will remove

@aidenkeating aidenkeating changed the title [WIP] AGDROID-686 Token integrity check AGDROID-686 Token integrity check Feb 6, 2018
@aidenkeating
Copy link
Contributor Author

aidenkeating commented Feb 6, 2018

@secondsun @ziccardi Removed unused singleton stuff and updated the android sdk bom stuff. Tests have started to pass again.

@aidenkeating
Copy link
Contributor Author

aidenkeating commented Feb 7, 2018

@secondsun Would you mind taking a look? One question, we currently have the auth module typed as keycloak because it matches up with the actual keycloak service. We also have a keycloak module in this SDK. I'm guessing them both being typed as keycloak is a bad thing? Should we modify the keycloak module to something else or remove it altogether as it will be replaced with the auth service?

@danielpassos
Copy link
Collaborator

@aidenkeating Keycloak Service is a temporary one, It was to help us in the core PoC and going to be removed

@aidenkeating
Copy link
Contributor Author

@danielpassos @ziccardi @secondsun Would you mind taking a look? I think this is ready to merge

Copy link
Member

@ziccardi ziccardi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple of comments

* @return <code>true</code> if user is authorized and token is not expired.
*/
public boolean checkValidAuth() {
return isAuthorized() && getNeedsRenewal();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't be return isAuthorized() && !getNeedsRenewal(); ?

*/
public synchronized void clear() {
if (!prefs.edit().remove(KEY_STATE).commit()) {
throw new IllegalStateException("Failed to clear state from shared preferences");
}
}

public static AuthStateManager getInstance(final Context context) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aidenkeating Just a proposal: we could add a bootstrap method with package level visibility. It could then be called from the bootstrap method of the AuthService. This way other classes will see only a getInstance with no parameters. WDYT?

@aidenkeating
Copy link
Contributor Author

aidenkeating commented Feb 8, 2018

@ziccardi @danielpassos Mind taking a look? Have move the AuthStateManager out to the auth package. Have also included an init(Context) function in the AuthService to allow the user to provide the context. This is following the example used in this PR https://github.com/aerogear/aerogear-android-sdk/pull/27/files#diff-7037942ee1f06907ac7d09f6d65ccd6dR88

* Authentication service singleton.
*/
private static AuthService INSTANCE;
public class AuthService implements ServiceModule {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I presume this won't compile because its not implementing the methods from ServiceModule right?

Also how is the AuthService object got now?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is. Well CircleCI tests are passing. Jenkins is failing because the gradle daemon decided to go ahead and stop.

The ServiceModule interface has changed in this PR #22

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right cool, thanks for explaining

@aidenkeating
Copy link
Contributor Author

@wtrocki Would you mind taking a look? I think this is ready to merge. Don't want this PR to bloat too much more. Jenkins appears to be failing because of an internal issue

@wtrocki wtrocki requested a review from JameelB February 8, 2018 16:57
@wtrocki wtrocki dismissed stale reviews from secondsun and ziccardi February 8, 2018 17:55

Changes were applied

Copy link
Contributor

@wtrocki wtrocki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Adjustments can be done later stage

@wtrocki wtrocki merged commit b71d208 into aerogear:master Feb 8, 2018
@wtrocki
Copy link
Contributor

wtrocki commented Feb 8, 2018

I have spent some time checking changes on local machine.
PR recieved pretty good feedback. Considering that this changes cannot be properly tested until we get login implementation I think it's best to get that into master and follow up with other PR's.

Really good job @aidenkeating

@danielpassos
Copy link
Collaborator

I didn't have time to review it, I was about to start now but it's already merged. I didn't test it but I have 2 comments about this PR:

  1. Correct or not all other modules are using org.aerogear.mobile.[module-name] as the package
  2. I think all method who going to throw the exception needs to have that explicit in the method not only in the Javadoc.

@aidenkeating
Copy link
Contributor Author

@danielpassos The package name was to address this comment #21 (comment) and this proposal https://github.com/aerogear/proposals/blob/master/sdks/SDK-naming.md#proposed-solution

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants