diff --git a/src/as/com/threerings/bureau/client/BureauClient.as b/src/as/com/threerings/bureau/client/BureauClient.as
index 9ec2d56d9..29191897b 100644
--- a/src/as/com/threerings/bureau/client/BureauClient.as
+++ b/src/as/com/threerings/bureau/client/BureauClient.as
@@ -39,13 +39,10 @@ public class BureauClient extends Client
public function BureauClient (token :String, bureauId :String)
{
super(null);
-
_bureauId = bureauId;
-
var creds :BureauCredentials = new BureauCredentials(_bureauId);
creds.sessionToken = token;
_creds = creds;
-
_ctx = createContext();
_director = createDirector();
}
diff --git a/src/as/com/threerings/bureau/data/BureauCredentials.as b/src/as/com/threerings/bureau/data/BureauCredentials.as
index 97c70d95a..f32f3f1ce 100644
--- a/src/as/com/threerings/bureau/data/BureauCredentials.as
+++ b/src/as/com/threerings/bureau/data/BureauCredentials.as
@@ -38,20 +38,26 @@ public class BureauCredentials extends Credentials
*/
public var sessionToken :String;
+ /**
+ * The id of the bureau logging in.
+ */
+ public var bureauId :String;
+
/**
* Creates new credentials for a specific bureau.
*/
- public function BureauCredentials (token :String)
+ public function BureauCredentials (bureauId :String)
{
- super(new Name("@@bureau:" + token + "@@"));
- sessionToken = token;
+ super(new Name("@@bureau:" + bureauId + "@@"));
+ this.bureauId = bureauId;
}
/** @inheritDoc */
override protected function toStringBuf (buf :StringBuilder) :void
{
super.toStringBuf(buf);
- buf.append(" token=").append(sessionToken);
+ buf.append(" bureauId=").append(bureauId).
+ append(" token=").append(sessionToken);
}
// from interface Streamable
@@ -59,6 +65,7 @@ public class BureauCredentials extends Credentials
{
super.readObject(ins);
sessionToken = (ins.readField(String) as String);
+ bureauId = (ins.readField(String) as String);
}
// from interface Streamable
@@ -66,6 +73,7 @@ public class BureauCredentials extends Credentials
{
super.writeObject(out);
out.writeField(sessionToken);
+ out.writeField(bureauId);
}
}
}
diff --git a/src/java/com/threerings/bureau/client/BureauClient.java b/src/java/com/threerings/bureau/client/BureauClient.java
index 03e552ce1..961e02ecb 100644
--- a/src/java/com/threerings/bureau/client/BureauClient.java
+++ b/src/java/com/threerings/bureau/client/BureauClient.java
@@ -41,13 +41,10 @@ public abstract class BureauClient extends Client
public BureauClient (String token, String bureauId, RunQueue runQueue)
{
super(null, runQueue);
-
_bureauId = bureauId;
-
BureauCredentials creds = new BureauCredentials(_bureauId);
creds.sessionToken = token;
_creds = creds;
-
_ctx = createContext();
_director = createDirector();
}
diff --git a/src/java/com/threerings/bureau/data/BureauCredentials.java b/src/java/com/threerings/bureau/data/BureauCredentials.java
index a9bc5efa8..5391c8b60 100644
--- a/src/java/com/threerings/bureau/data/BureauCredentials.java
+++ b/src/java/com/threerings/bureau/data/BureauCredentials.java
@@ -35,6 +35,20 @@ public class BureauCredentials extends Credentials
*/
public String sessionToken;
+ /**
+ * The id of the bureau logging in.
+ */
+ public String bureauId;
+
+ /**
+ * Test if a given name object matches the name that we generate.
+ */
+ public static boolean isBureau (Name name)
+ {
+ String normal = name.getNormal();
+ return normal.startsWith("@@bureau:") && normal.endsWith("@@");
+ }
+
/**
* Creates an empty credentials for streaming. Should not be used directly.
*/
@@ -48,18 +62,14 @@ public class BureauCredentials extends Credentials
public BureauCredentials (String bureauId)
{
super(new Name("@@bureau:" + bureauId + "@@"));
+ this.bureauId = bureauId;
}
@Override // inherit documentation
protected void toString (StringBuilder buf)
{
super.toString(buf);
- buf.append(" token=").append(sessionToken);
- }
-
- // inherit documentation - from Object
- public String toString ()
- {
- return super.toString() + ", token=" + sessionToken;
+ buf.append(" id=").append(bureauId).
+ append(" token=").append(sessionToken);
}
}
diff --git a/src/java/com/threerings/bureau/server/BureauRegistry.java b/src/java/com/threerings/bureau/server/BureauRegistry.java
index 6c17b2c91..62f0386b2 100644
--- a/src/java/com/threerings/bureau/server/BureauRegistry.java
+++ b/src/java/com/threerings/bureau/server/BureauRegistry.java
@@ -25,6 +25,7 @@ import java.util.Map;
import java.util.Set;
import com.threerings.bureau.data.AgentObject;
import com.threerings.bureau.data.BureauCodes;
+import com.threerings.bureau.data.BureauCredentials;
import com.threerings.presents.data.ClientObject;
import com.threerings.presents.dobj.RootDObjectManager;
import com.threerings.presents.dobj.ObjectDeathListener;
@@ -67,6 +68,21 @@ public class BureauRegistry
String token);
}
+ /**
+ * Thrown when a bureau could not be authenticated.
+ */
+ public static class AuthenticationException extends Exception
+ {
+ /**
+ * Creates a new authentication exception with a message explaining why the client could
+ * not be authenticated as a bureau.
+ */
+ public AuthenticationException (String message)
+ {
+ super(message);
+ }
+ }
+
/**
* Creates a new registry, prepared to provide bureau services.
*/
@@ -101,6 +117,30 @@ public class BureauRegistry
BureauCodes.BUREAU_GROUP);
}
+ /**
+ * Check the credentials to make sure this is one of our bureaus.
+ */
+ public void authenticate (BureauCredentials creds)
+ throws AuthenticationException
+ {
+ Bureau bureau = _bureaus.get(creds.bureauId);
+ if (bureau == null) {
+ throw new AuthenticationException(
+ "Bureau " + creds.bureauId + " not found");
+ }
+
+ if (bureau.clientObj != null) {
+ throw new AuthenticationException(
+ "Bureau " + creds.bureauId + " already logged in");
+ }
+
+ if (!bureau.token.equals(creds.sessionToken)) {
+ throw new AuthenticationException(
+ "Bureau " + creds.bureauId +
+ " does not match credentials token");
+ }
+ }
+
/**
* Registers a command generator for a given type. When an agent is started and no bureaus are
* running, the bureauType is used to determine the CommandGenerator
@@ -155,12 +195,12 @@ public class BureauRegistry
bureau = new Bureau();
bureau.bureauId = agent.bureauId;
+ bureau.token = generateToken();
// schedule the bureau to be kicked off
- String token = generateToken();
bureau.builder = new ProcessBuilder(
generator.createCommand(
- _serverNameAndPort, agent.bureauId, token));
+ _serverNameAndPort, agent.bureauId, bureau.token));
bureau.builder.redirectErrorStream(true);
@@ -514,6 +554,9 @@ public class BureauRegistry
// non-null once the bureau is scheduled but not yet kicked off
ProcessBuilder builder;
+ // The token given to this bureau for authentication
+ String token;
+
// The bureau's key in the map of bureaus. All requests for this bureau
// with this id should be associated with one instance
String bureauId;