Skip to content

Commit 2db7922

Browse files
authored
Merge pull request #97 from mngoe/feature-31351
bypass the csrfToken with specific User-agent
2 parents 5542455 + b1d51a7 commit 2db7922

File tree

7 files changed

+111
-2
lines changed

7 files changed

+111
-2
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
mutation GetCsrfToken {
2+
getCsrfToken {
3+
csrfToken
4+
}
5+
}

claimManagement/src/main/graphql/org.openimis.imisclaim/schema.graphqls

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4472,6 +4472,11 @@ Skip indicates that the claim is not selected for review
44724472
revokeToken(refreshToken: String): Revoke
44734473
deleteTokenCookie: DeleteJSONWebTokenCookie
44744474
deleteRefreshTokenCookie: DeleteRefreshTokenCookie
4475+
getCsrfToken: GetCsrfTokenMutationPayload
4476+
}
4477+
4478+
type GetCsrfTokenMutationPayload {
4479+
csrfToken: String
44754480
}
44764481

44774482
type GenerateTimeframeInvoicesPayload {

claimManagement/src/main/java/org/openimis/imisclaims/Global.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ public class Global extends Application {
6565
private static final String SHPREF_NAME = "SHPref";
6666
private static final String SHPREF_LANGUAGE = "language";
6767
private static final String DEFAULT_LANGUAGE_CODE = "en";
68+
private static final String SHPREF_CSRF = "csrfToken";
6869
private static Global instance;
6970
private String OfficerCode;
7071
private String OfficerHealthFacility;
@@ -137,6 +138,11 @@ public Token getJWTToken() {
137138
return JWTToken;
138139
}
139140

141+
public String getCsrfToken(){
142+
SharedPreferences sp = getDefaultSharedPreferences();
143+
return sp.getString(SHPREF_CSRF,null);
144+
}
145+
140146
public boolean isLoggedIn() {
141147
boolean isLoggedIn = getJWTToken().isTokenValidJWT();
142148
if (!isLoggedIn) {

claimManagement/src/main/java/org/openimis/imisclaims/network/okhttp/AuthorizationInterceptor.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import org.openimis.imisclaims.Global;
88
import org.openimis.imisclaims.Token;
9+
import org.openimis.imisclaims.tools.Log;
910

1011
import java.io.IOException;
1112
import java.net.HttpURLConnection;
@@ -22,14 +23,17 @@ public class AuthorizationInterceptor implements Interceptor {
2223
public AuthorizationInterceptor(@NonNull Global global) {
2324
this.global = global;
2425
}
26+
private static final String USER_AGENT = "mobile_app";
2527

2628
@NonNull
2729
@Override
2830
public Response intercept(@NonNull Chain chain) throws IOException {
2931
Token token = global.getJWTToken();
32+
String csrfToken = global.getCsrfToken();
3033
if (token != null && token.isTokenValidJWT()) {
3134
Request.Builder builder = chain.request().newBuilder();
3235
builder.addHeader("Authorization", "bearer " + token.getTokenText().trim());
36+
builder.addHeader("User-Agent", USER_AGENT);
3337
Response response = chain.proceed(builder.build());
3438
if (response.code() == HttpURLConnection.HTTP_UNAUTHORIZED) {
3539
global.getJWTToken().clearToken();

claimManagement/src/main/java/org/openimis/imisclaims/network/request/BaseGraphQLRequest.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import com.apollographql.apollo.ApolloCall;
77
import com.apollographql.apollo.ApolloClient;
8+
import com.apollographql.apollo.api.Mutation;
89
import com.apollographql.apollo.api.Operation;
910
import com.apollographql.apollo.api.Query;
1011
import com.apollographql.apollo.api.Response;
@@ -14,9 +15,11 @@
1415
import org.openimis.imisclaims.network.apollo.DateCustomTypeAdapter;
1516
import org.openimis.imisclaims.network.apollo.DateTimeCustomTypeAdapter;
1617
import org.openimis.imisclaims.network.apollo.DecimalCustomTypeAdapter;
18+
import org.openimis.imisclaims.network.exception.HttpException;
1719
import org.openimis.imisclaims.network.util.OkHttpUtils;
1820
import org.openimis.imisclaims.type.CustomType;
1921

22+
import java.net.HttpURLConnection;
2023
import java.util.concurrent.Semaphore;
2124
import java.util.concurrent.TimeUnit;
2225
import java.util.concurrent.TimeoutException;
@@ -62,4 +65,54 @@ public void onFailure(@NonNull ApolloException e) {
6265
}
6366
return responses[0];
6467
}
68+
69+
@NonNull
70+
@WorkerThread
71+
protected <T extends Operation.Data> Response<T> makeSynchronous(Operation<T, ?, ?> query) throws Exception {
72+
Semaphore semaphore = new Semaphore(0);
73+
final Exception[] exceptions = new Exception[1];
74+
final Response<T>[] responses = new Response[1];
75+
ApolloCall<?> call;
76+
if (query instanceof Query) {
77+
call = apolloClient.query((Query<T, ?, ?>) query);
78+
} else if(query instanceof Mutation) {
79+
call = apolloClient.mutate((Mutation<T, ?, ?>) query);
80+
} else {
81+
throw new IllegalArgumentException("Query is unsupported");
82+
}
83+
call.enqueue(new ApolloCall.Callback() {
84+
@Override
85+
public void onResponse(@NonNull Response response) {
86+
responses[0] = response;
87+
semaphore.release();
88+
}
89+
90+
@Override
91+
public void onFailure(@NonNull ApolloException e) {
92+
exceptions[0] = e;
93+
semaphore.release();
94+
}
95+
});
96+
if (!semaphore.tryAcquire(TIME_OUT_IN_MS, TimeUnit.MILLISECONDS)) {
97+
throw new TimeoutException("Call couldn't finish within " + TIME_OUT_IN_MS + "ms");
98+
}
99+
Exception exception = exceptions[0];
100+
if (exception != null) {
101+
throw exception;
102+
}
103+
Response<T> response = responses[0];
104+
if (response.hasErrors()) {
105+
String details = response.getErrors().get(0).getMessage();
106+
if (details.equals("User not authorized for this operation")) {
107+
throw new HttpException(
108+
HttpURLConnection.HTTP_UNAUTHORIZED,
109+
details,
110+
null,
111+
null
112+
);
113+
}
114+
throw new RuntimeException(response.toString());
115+
}
116+
return response;
117+
}
65118
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package org.openimis.imisclaims.network.request;
2+
3+
import androidx.annotation.NonNull;
4+
import androidx.annotation.WorkerThread;
5+
6+
import org.openimis.imisclaims.GetCsrfTokenMutation;
7+
8+
import java.util.Objects;
9+
10+
public class GetCsrfTokenGraphQLMutation extends BaseGraphQLRequest {
11+
12+
@WorkerThread
13+
@NonNull
14+
public String get() throws Exception {
15+
com.apollographql.apollo.api.Response<GetCsrfTokenMutation.Data> response = makeSynchronous(new GetCsrfTokenMutation());
16+
return Objects.requireNonNull(
17+
Objects.requireNonNull(
18+
Objects.requireNonNull(response.getData(), "data is null")
19+
.getCsrfToken(), "csrfToken is null"
20+
).csrfToken(), "csrfToken is null");
21+
}
22+
}

claimManagement/src/main/java/org/openimis/imisclaims/usecase/Login.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
package org.openimis.imisclaims.usecase;
22

3+
import android.content.SharedPreferences;
4+
35
import androidx.annotation.NonNull;
46
import androidx.annotation.WorkerThread;
57

68
import org.openimis.imisclaims.Global;
79
import org.openimis.imisclaims.network.dto.LoginDto;
810
import org.openimis.imisclaims.network.dto.TokenDto;
11+
import org.openimis.imisclaims.network.request.GetCsrfTokenGraphQLMutation;
912
import org.openimis.imisclaims.network.request.LoginRequest;
13+
import org.openimis.imisclaims.tools.Log;
1014

1115
import java.util.concurrent.TimeUnit;
1216

@@ -16,17 +20,22 @@ public class Login {
1620
private final LoginRequest request;
1721
@NonNull
1822
private final Global global;
23+
@NonNull
24+
private final GetCsrfTokenGraphQLMutation getCsrfTokenGraphQLMutation;
25+
private static final String SHPREF_CSRF = "csrfToken";
1926

2027
public Login(
2128
@NonNull LoginRequest request,
22-
@NonNull Global global
29+
@NonNull Global global,
30+
@NonNull GetCsrfTokenGraphQLMutation getCsrfTokenGraphQLMutation
2331
) {
2432
this.request = request;
2533
this.global = global;
34+
this.getCsrfTokenGraphQLMutation = getCsrfTokenGraphQLMutation;
2635
}
2736

2837
public Login() {
29-
this(new LoginRequest(), Global.getGlobal());
38+
this(new LoginRequest(), Global.getGlobal(), new GetCsrfTokenGraphQLMutation());
3039
}
3140

3241
@WorkerThread
@@ -37,6 +46,11 @@ public void execute(@NonNull String username, String password) {
3746
token.getToken(),
3847
TimeUnit.SECONDS.toMillis(token.getExpiresOn())
3948
);
49+
String csrfToken = getCsrfTokenGraphQLMutation.get();
50+
SharedPreferences sp = global.getDefaultSharedPreferences();
51+
SharedPreferences.Editor editor = sp.edit();
52+
editor.putString(SHPREF_CSRF, csrfToken);
53+
editor.apply();
4054
} catch (Exception e) {
4155
e.printStackTrace();
4256
}

0 commit comments

Comments
 (0)