Skip to content

Commit 2bf9e05

Browse files
dfirshtboopt2
authored andcommitted
Auth unauth (#20)
* added explict authorize and unauthorize methods * disable autologging in on rpc and wrote a test for this behavor * updated README * fixed README typo * Added race condition test * check for auth success in tests setup * added warnings when auth/unauth is unnecessarily called * added more detail to the README example * added more auth tests * removed unused import * fixed main function * added test for action after unauth
1 parent 21eb2d6 commit 2bf9e05

File tree

9 files changed

+452
-102
lines changed

9 files changed

+452
-102
lines changed

README.md

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,25 @@ Applications use the CSync class to create a connection to a specific CSync serv
9595
final CSync csync = new CSync.builder()
9696
.host("localhost")
9797
.port(6005)
98-
.provider("demo")
99-
.token("demoToken")
10098
.build();
10199
```
102100

103-
Note: Update the `host` and `port` to your specific csync server instance. Also, `provider` and `token` can be updated to allow other providers to authenticate the csync session.
101+
Note: Update the `host` and `port` to your specific csync server instance.
102+
103+
## Authenticating
104+
```
105+
csync.authenticate("demo", "demoToken")
106+
.onComplete((exception, didSucceed) -> {
107+
if(didSucceed) {
108+
//We successfully logged in
109+
}
110+
else {
111+
ex.printStackTrace()
112+
}
113+
});
114+
```
115+
116+
Note: The provider and token can be updated to allow other providers to authenticate the csync session.
104117

105118
## Listening to values on a key
106119
```

src/main/java/Main.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,8 @@ public static void main(String args[]) throws Exception {
4242

4343

4444
final CSync csync = CSync.builder()
45-
.token("demoToken")
46-
.provider("demo")
4745
.build();
46+
csync.authenticate("demo", "demoToken");
4847

4948
csync.pub("something", "hello", Acls.Private)
5049
.then(() -> csync.pub("something", "hello again", Acls.PublicRead))

src/main/java/com/ibm/csync/CSync.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@
2222
import com.ibm.csync.functional.Futur;
2323
import com.ibm.csync.impl.CSyncImpl;
2424
import com.ibm.csync.impl.commands.Pub;
25+
import okhttp3.ws.WebSocket;
2526

2627
import java.io.Closeable;
28+
import java.io.IOException;
2729
import java.io.UnsupportedEncodingException;
2830
import java.net.URLEncoder;
2931
import java.util.HashMap;
@@ -69,9 +71,17 @@ public Futur<Long> del(final Key key, final Deadline dl) {
6971

7072

7173

74+
// Auth
75+
76+
@Override
77+
public Futur<Boolean> authenticate(String provider, String token) {
78+
return impl.ws.startSession(provider, token);
79+
}
7280

73-
74-
81+
@Override
82+
public Futur<Boolean> unauthenticate() {
83+
return impl.ws.endSession();
84+
}
7585

7686
// Blocking
7787

@@ -175,16 +185,6 @@ public Builder path(final String path) {
175185
return this;
176186
}
177187

178-
public Builder provider(final String provider){
179-
args.put("authProvider",provider);
180-
return this;
181-
}
182-
183-
public Builder token(final String token) {
184-
args.put("token",token);
185-
return this;
186-
}
187-
188188
private static String encode(final String in) {
189189
try {
190190
return URLEncoder.encode(in,"UTF-8");

src/main/java/com/ibm/csync/CSyncAPI.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,15 @@
1919
package com.ibm.csync;
2020

2121
import com.ibm.csync.functional.Futur;
22+
import okhttp3.ws.WebSocket;
23+
24+
import java.io.IOError;
25+
import java.io.IOException;
2226

2327
interface CSyncAPI {
2428

29+
Futur<Boolean> authenticate(String provider, String token);
30+
Futur<Boolean> unauthenticate();
2531
Futur<Long> pub(Key key, String data, Acl acl, Deadline dl);
2632
Futur<Long> del(final Key key, final Deadline dl);
2733
Timeout defaultTimeout();

src/main/java/com/ibm/csync/impl/Transport.java

Lines changed: 74 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
import org.slf4j.LoggerFactory;
3939

4040
import java.io.IOException;
41+
import java.io.UnsupportedEncodingException;
42+
import java.net.URLEncoder;
4143
import java.util.Collections;
4244
import java.util.Map;
4345
import java.util.WeakHashMap;
@@ -55,6 +57,7 @@ public class Transport implements WebSocketListener {
5557

5658
private Promise<WebSocket> socketPromise = null;
5759
private Futur<WebSocket> socketFutur = null;
60+
private Promise<Boolean> finshedClosing = null;
5861
private final Executor sendExec = Executors.newSingleThreadExecutor();
5962
private WebSocket loginWebSocket = null; //Needs to be stored so that we callback when we are sure auth succeeded
6063
// TODO: handle concurrency
@@ -63,11 +66,10 @@ public class Transport implements WebSocketListener {
6366

6467
private final Tracer tracer;
6568

66-
//private final String url;
6769
private final Database db;
6870
private final ScheduledExecutorService workers;
6971

70-
private final Request req;
72+
private Request req;
7173
private final OkHttpClient client;
7274

7375
Transport(final String url, final Database db, final ScheduledExecutorService workers, final Tracer tracer) {
@@ -77,17 +79,64 @@ public class Transport implements WebSocketListener {
7779
this.tracer = tracer;
7880

7981
req = new Request.Builder()
80-
.get()
81-
.url(url)
82-
.build();
82+
.get()
83+
.url(url)
84+
.build();
8385

8486
client = new OkHttpClient.Builder()
8587
.readTimeout(60, TimeUnit.SECONDS)
8688
.writeTimeout(60, TimeUnit.SECONDS).build();
8789

8890
}
8991

90-
private synchronized Futur<WebSocket> connect() {
92+
public synchronized Futur<Boolean> startSession(String provider, String token) {
93+
String authURL = this.req.url().toString() + encodeAuthParameters(provider, token);
94+
Promise<Boolean> sessionPromise = new Promise<>();
95+
if(socketFutur != null) {
96+
// Already logged in
97+
logger.warn("Start session called while the session is already active");
98+
sessionPromise.set(null, true);
99+
}
100+
else {
101+
connect(authURL)
102+
.onComplete(workers, (ex, ws) -> {
103+
if (ex != null) {
104+
sessionPromise.set(ex,false);
105+
}
106+
else {
107+
sessionPromise.set(null,true);
108+
}
109+
}
110+
111+
);
112+
}
113+
return sessionPromise.futur;
114+
}
115+
116+
public synchronized Futur<Boolean> endSession() {
117+
if(socketFutur == null) {
118+
// Already logged out
119+
logger.warn("End session called while the session is already not active");
120+
Promise<Boolean> willLogout = new Promise<>();
121+
Futur<Boolean> logoutSuccess = willLogout.futur;
122+
willLogout.set(null, true);
123+
return logoutSuccess;
124+
}
125+
else {
126+
if(finshedClosing != null) {
127+
return finshedClosing.futur;
128+
}
129+
finshedClosing = new Promise<>();
130+
socketFutur.consume(ws -> ws.close(1000,"session ended"));
131+
return finshedClosing.futur;
132+
}
133+
}
134+
135+
private synchronized Futur<WebSocket> connect(String url) {
136+
Request req = new Request.Builder()
137+
.get()
138+
.url(url)
139+
.build();
91140
if (socketFutur == null) {
92141
socketPromise = new Promise<>(workers);
93142
socketFutur = socketPromise.futur;
@@ -96,7 +145,22 @@ private synchronized Futur<WebSocket> connect() {
96145
return socketFutur;
97146
}
98147

148+
private String encodeAuthParameters(String provider, String token) {
149+
try {
150+
return "&authProvider=" + URLEncoder.encode(provider,"UTF-8")
151+
+ "&token=" + URLEncoder.encode(token,"UTF-8");
152+
} catch (UnsupportedEncodingException e) {
153+
throw new RuntimeException(e);
154+
}
155+
}
156+
99157
public synchronized <T> Futur<T> rpc(final String kind, final Object request, Class<T> cls, final Deadline dl) {
158+
if(socketFutur == null) {
159+
// Unauthenticated
160+
Promise<T> failedPromise = new Promise<>();
161+
failedPromise.set(new Exception("Unauthorized"), null);
162+
return failedPromise.futur;
163+
}
100164
final Envelope requestEnv = new Envelope(kind, gson.toJsonTree(request));
101165
final Long closure = requestEnv.closure;
102166
final String outgoing = gson.toJson(requestEnv);
@@ -105,7 +169,7 @@ public synchronized <T> Futur<T> rpc(final String kind, final Object request, C
105169
final Promise<Envelope> responseEnvelopePromise = new Promise<>(workers);
106170
waitingForResponse.put(closure, responseEnvelopePromise);
107171

108-
return connect()
172+
return socketFutur
109173
.consume(sendExec,ws -> ws.sendMessage(RequestBody.create(WebSocket.TEXT, outgoing)))
110174
.then(() -> responseEnvelopePromise.futur)
111175
.map(env -> gson.fromJson(env.payload,cls))
@@ -193,7 +257,8 @@ public synchronized void onClose(int code, String reason) {
193257
if (thePromise != null) {
194258
thePromise.set(new Exception(reason),null);
195259
}
196-
260+
if (finshedClosing != null) {
261+
finshedClosing.set(null, true);
262+
}
197263
}
198-
199264
}

src/test/java/com/ibm/csync/AdvanceTestsIT.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.util.concurrent.TimeUnit;
3030

3131
import static org.junit.Assert.assertTrue;
32+
import static org.junit.Assert.fail;
3233

3334
public class AdvanceTestsIT {
3435

@@ -37,13 +38,22 @@ public class AdvanceTestsIT {
3738

3839
@Before
3940
public void setup() throws Exception{
40-
int x = 50;
41+
CompletableFuture<Boolean> future = new CompletableFuture<>();
4142
csync = CSync.builder()
42-
.token(System.getenv("CSYNC_DEMO_TOKEN"))
43-
.provider(System.getenv("CSYNC_DEMO_PROVIDER"))
4443
.host(System.getenv("CSYNC_HOST"))
4544
.port(Integer.parseInt(System.getenv("CSYNC_PORT")))
4645
.build();
46+
csync.authenticate(System.getenv("CSYNC_DEMO_PROVIDER"), System.getenv("CSYNC_DEMO_TOKEN"))
47+
.onComplete((ex, isSuccessful) -> {
48+
if(ex == null) {
49+
future.complete(true);
50+
}
51+
else {
52+
fail("Unable to authenticate with the given credentials");
53+
}
54+
});
55+
56+
future.get(10, TimeUnit.SECONDS);
4757
}
4858

4959
@After

0 commit comments

Comments
 (0)