Merge pull request #447 from BeaudanBrown/auth-sending

[Public Authentication] Auth sending
pull/453/head
Beaudan Campbell-Brown 6 years ago committed by GitHub
commit 63293c5b03
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -95,7 +95,7 @@ module.exports = {
saveConversations,
getConversationById,
savePublicServerToken,
getPublicServerTokenByServerName,
getPublicServerTokenByServerUrl,
updateConversation,
removeConversation,
getAllConversations,
@ -795,7 +795,7 @@ async function updateToLokiSchemaVersion1(currentVersion, instance) {
await instance.run(
`CREATE TABLE servers(
server STRING PRIMARY KEY ASC,
serverUrl STRING PRIMARY KEY ASC,
token TEXT
);`
);
@ -833,7 +833,7 @@ async function updateToLokiSchemaVersion1(currentVersion, instance) {
};
const lokiPublicServerData = {
server: 'chat.lokinet.org',
serverUrl: 'https://chat.lokinet.org',
token: null,
};
@ -851,24 +851,24 @@ async function updateToLokiSchemaVersion1(currentVersion, instance) {
const publicChatData = {
...baseData,
id: `publicChat:1@${lokiPublicServerData.server}`,
server: lokiPublicServerData.server,
id: 'publicChat:1@chat.lokinet.org',
server: lokiPublicServerData.serverUrl,
name: 'Loki Public Chat',
channelId: '1',
};
const { server, token } = lokiPublicServerData;
const { serverUrl, token } = lokiPublicServerData;
await instance.run(
`INSERT INTO servers (
server,
serverUrl,
token
) values (
$server,
$serverUrl,
$token
);`,
{
$server: server,
$serverUrl: serverUrl,
$token: token,
}
);
@ -1622,27 +1622,27 @@ async function removeConversation(id) {
}
async function savePublicServerToken(data) {
const { server, token } = data;
const { serverUrl, token } = data;
await db.run(
`INSERT OR REPLACE INTO servers (
server,
serverUrl,
token
) values (
$server,
$serverUrl,
$token
)`,
{
$server: server,
$serverUrl: serverUrl,
$token: token,
}
);
}
async function getPublicServerTokenByServerName(server) {
async function getPublicServerTokenByServerUrl(serverUrl) {
const row = await db.get(
'SELECT * FROM servers WHERE server = $server;',
'SELECT * FROM servers WHERE serverUrl = $serverUrl;',
{
$server: server,
$serverUrl: serverUrl,
}
);

@ -11,6 +11,7 @@
clipboard,
BlockedNumberController,
lokiP2pAPI,
lokiPublicChatAPI,
JobQueue
*/
@ -1374,8 +1375,9 @@
const options = this.getSendOptions();
options.messageType = message.get('type');
options.isPublic = this.isPublic();
if (this.isPublic()) {
options.publicEndpoint = this.getEndpoint();
options.publicSendData = await this.getPublicSendData();
}
const groupNumbers = this.getRecipients();
@ -2064,17 +2066,24 @@
return {
server: this.get('server'),
channelId: this.get('channelId'),
conversationId: this.get('id'),
};
},
// FIXME: remove or add public and/or "sending" hint to name...
getEndpoint() {
if (!this.isPublic()) {
return null;
}
const server = this.get('server');
const channelId = this.get('channelId');
const endpoint = `${server}/channels/${channelId}/messages`;
return endpoint;
async getPublicSendData() {
const serverAPI = lokiPublicChatAPI.findOrCreateServer(
this.get('server')
);
// Can be null if fails
const token = await serverAPI.getOrRefreshServerToken();
const channelAPI = serverAPI.findOrCreateChannel(
this.get('channelId'),
this.id
);
const publicEndpoint = channelAPI.getEndpoint();
return {
publicEndpoint,
token,
};
},
// SIGNAL PROFILES

@ -122,7 +122,7 @@ module.exports = {
getAllPublicConversations,
getPublicConversationsByServer,
savePublicServerToken,
getPublicServerTokenByServerName,
getPublicServerTokenByServerUrl,
getAllGroupsInvolvingId,
searchConversations,
@ -773,8 +773,8 @@ async function savePublicServerToken(data) {
await channels.savePublicServerToken(data);
}
async function getPublicServerTokenByServerName(server) {
const token = await channels.getPublicServerTokenByServerName(server);
async function getPublicServerTokenByServerUrl(serverUrl) {
const token = await channels.getPublicServerTokenByServerUrl(serverUrl);
return token;
}

@ -78,8 +78,9 @@ class LokiMessageAPI {
async sendMessage(pubKey, data, messageTimeStamp, ttl, options = {}) {
const {
isPing = false,
isPublic = false,
numConnections = DEFAULT_CONNECTIONS,
publicEndpoint = null,
publicSendData = null,
} = options;
// Data required to identify a message in a conversation
const messageEventData = {
@ -87,10 +88,14 @@ class LokiMessageAPI {
timestamp: messageTimeStamp,
};
// FIXME: should have public/sending(ish hint) in the option to make
// this more obvious...
if (publicEndpoint) {
// could we emit back to LokiPublicChannelAPI somehow?
if (isPublic) {
const { token, publicEndpoint } = publicSendData;
if (!token) {
throw new window.textsecure.PublicChatError(
`Failed to retrieve valid token for ${publicEndpoint}`
);
}
const { profile } = data;
let displayName = 'Anonymous';
if (profile && profile.displayName) {
@ -109,24 +114,34 @@ class LokiMessageAPI {
},
],
};
let result;
try {
const result = await nodeFetch(publicEndpoint, {
result = await nodeFetch(publicEndpoint, {
method: 'post',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer loki',
Authorization: `Bearer ${token}`,
},
body: JSON.stringify(payload),
});
const body = await result.json();
messageEventData.serverId = body.data.id;
window.Whisper.events.trigger('publicMessageSent', messageEventData);
return;
} catch (e) {
throw new window.textsecure.PublicChatError(
'Failed to send public chat message.'
`Failed to send public chat message: ${e}`
);
}
const body = await result.json();
if (!result.ok) {
if (result.status === 401) {
// TODO: Handle token timeout
}
const error = body.meta.error_message;
throw new window.textsecure.PublicChatError(
`Failed to send public chat message: ${error}`
);
}
messageEventData.serverId = body.data.id;
window.Whisper.events.trigger('publicMessageSent', messageEventData);
return;
}
const data64 = dcodeIO.ByteBuffer.wrap(data).toString('base64');

@ -46,12 +46,11 @@ class LokiPublicChatAPI extends EventEmitter {
}
class LokiPublicServerAPI {
constructor(chatAPI, hostport) {
constructor(chatAPI, url) {
this.chatAPI = chatAPI;
this.server = hostport;
this.channels = [];
this.tokenPromise = null;
this.baseServerUrl = `https://${this.server}`;
this.baseServerUrl = url;
}
findOrCreateChannel(channelId, conversationId) {
let thisChannel = this.channels.find(
@ -80,12 +79,14 @@ class LokiPublicServerAPI {
}
async getOrRefreshServerToken() {
let token = await Signal.Data.getPublicServerTokenByServerName(this.server);
let token = await Signal.Data.getPublicServerTokenByServerUrl(
this.baseServerUrl
);
if (!token) {
token = await this.refreshServerToken();
if (token) {
await Signal.Data.savePublicServerToken({
server: this.server,
serverUrl: this.baseServerUrl,
token,
});
}
@ -176,7 +177,7 @@ class LokiPublicChannelAPI {
}
getEndpoint() {
const endpoint = `https://${this.serverAPI.server}/channels/${
const endpoint = `${this.serverAPI.baseServerUrl}/channels/${
this.channelId
}/messages`;
return endpoint;
@ -255,7 +256,10 @@ class LokiPublicChannelAPI {
let timestamp = new Date(adnMessage.created_at).getTime();
let from = adnMessage.user.username;
let source;
if (adnMessage.annotations.length) {
if (adnMessage.is_deleted) {
return;
}
if (adnMessage.annotations !== []) {
const noteValue = adnMessage.annotations[0].value;
({ from, timestamp, source } = noteValue);
}

@ -34,8 +34,8 @@
async function DHDecrypt(symmetricKey, ivAndCiphertext) {
const iv = ivAndCiphertext.slice(0, IV_LENGTH);
const cipherText = ivAndCiphertext.slice(IV_LENGTH);
return libsignal.crypto.decrypt(symmetricKey, cipherText, iv);
const ciphertext = ivAndCiphertext.slice(IV_LENGTH);
return libsignal.crypto.decrypt(symmetricKey, ciphertext, iv);
}
class FallBackSessionCipher {
@ -131,18 +131,18 @@
return this._ephemeralPubKeyHex;
}
async decrypt(snodeAddress, ivAndCipherTextBase64) {
const ivAndCipherText = dcodeIO.ByteBuffer.wrap(
ivAndCipherTextBase64,
async decrypt(snodeAddress, ivAndCiphertextBase64) {
const ivAndCiphertext = dcodeIO.ByteBuffer.wrap(
ivAndCiphertextBase64,
'base64'
).toArrayBuffer();
const symmetricKey = await this._getSymmetricKey(snodeAddress);
try {
const decrypted = await DHDecrypt(symmetricKey, ivAndCipherText);
const decrypted = await DHDecrypt(symmetricKey, ivAndCiphertext);
const decoder = new TextDecoder();
return decoder.decode(decrypted);
} catch (e) {
return ivAndCipherText;
return ivAndCiphertext;
}
}
@ -153,17 +153,15 @@
plainText = textEncoder.encode(plainText);
}
const symmetricKey = await this._getSymmetricKey(snodeAddress);
const cipherText = await DHEncrypt(symmetricKey, plainText);
return dcodeIO.ByteBuffer.wrap(cipherText).toString('base64');
const ciphertext = await DHEncrypt(symmetricKey, plainText);
return dcodeIO.ByteBuffer.wrap(ciphertext).toString('base64');
}
}
async function decryptToken({ ivAndCipherText64, serverPubKey64 }) {
const ivAndCipherText = new Uint8Array(
dcodeIO.ByteBuffer.fromBase64(ivAndCipherText64).toArrayBuffer()
async function decryptToken({ cipherText64, serverPubKey64 }) {
const ivAndCiphertext = new Uint8Array(
dcodeIO.ByteBuffer.fromBase64(cipherText64).toArrayBuffer()
);
const iv = ivAndCipherText.slice(0, IV_LENGTH);
const cipherText = ivAndCipherText.slice(IV_LENGTH);
const serverPubKey = new Uint8Array(
dcodeIO.ByteBuffer.fromBase64(serverPubKey64).toArrayBuffer()
@ -174,7 +172,8 @@
privKey
);
const token = await libsignal.crypto.decrypt(symmetricKey, cipherText, iv);
const token = await DHDecrypt(symmetricKey, ivAndCiphertext);
const tokenString = dcodeIO.ByteBuffer.wrap(token).toString('utf8');
return tokenString;
}

@ -49,11 +49,13 @@ function OutgoingMessage(
online,
messageType,
isPing,
publicEndpoint,
isPublic,
publicSendData,
} =
options || {};
this.numberInfo = numberInfo;
this.publicEndpoint = publicEndpoint;
this.isPublic = isPublic;
this.publicSendData = publicSendData;
this.senderCertificate = senderCertificate;
this.online = online;
this.messageType = messageType || 'outgoing';
@ -201,8 +203,9 @@ OutgoingMessage.prototype = {
numConnections: NUM_SEND_CONNECTIONS,
isPing: this.isPing,
};
if (this.publicEndpoint) {
options.publicEndpoint = this.publicEndpoint;
options.isPublic = this.isPublic;
if (this.isPublic) {
options.publicSendData = this.publicSendData;
}
await lokiMessageAPI.sendMessage(pubKey, data, timestamp, ttl, options);
} catch (e) {
@ -270,7 +273,7 @@ OutgoingMessage.prototype = {
},
doSendMessage(number, deviceIds, recurse) {
const ciphers = {};
if (this.publicEndpoint) {
if (this.isPublic) {
return this.transmitMessage(
number,
this.message.dataMessage,

@ -943,7 +943,7 @@ MessageSender.prototype = {
) {
const me = textsecure.storage.user.getNumber();
let numbers = groupNumbers.filter(number => number !== me);
if (options.publicEndpoint) {
if (options.isPublic) {
numbers = [groupId];
}
const profile = textsecure.storage.impl.getLocalProfile();

Loading…
Cancel
Save