Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #139 from hackers267/auth
Auth add some function to prepare the auth
- Loading branch information
Showing
10 changed files
with
289 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { Credential, Document } from "../types.ts"; | ||
|
||
export abstract class AuthPlugin { | ||
abstract prepare(credential: Credential): Document; | ||
auth() {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import { createHash, HmacSha1, pbkdf2Sync, randomBytes } from "../../deps.ts"; | ||
import { Binary } from "../../bson/mod.ts"; | ||
|
||
export function passwordDigest(username: string, password: string): string { | ||
const hash = createHash("md5"); | ||
hash.update(`${username}:mongo:${password}`); | ||
return hash.toString(); | ||
} | ||
export function HI(data: string, salt: string, iterations: number) { | ||
return pbkdf2Sync(data, salt, iterations, 20, "sha1"); | ||
} | ||
export function clientKeyFor(key: string) { | ||
return keyFor(key, "Client Key"); | ||
} | ||
|
||
/** | ||
* @param serverKey | ||
* @param key | ||
* @return string | ||
*/ | ||
function keyFor(key: string, serverKey: string): string { | ||
return new HmacSha1(key).update(serverKey).hex(); | ||
} | ||
|
||
export function serverKeyFor(key: string) { | ||
return keyFor(key, "Server Key"); | ||
} | ||
|
||
export function storedKeyFor(data: string) { | ||
return createHash("sha1").update(data).toString(); | ||
} | ||
|
||
export function nonceFor() { | ||
return randomBytes(24); | ||
} | ||
export function clientFirstMessageBare(username: string, nonce: Uint8Array) { | ||
return Uint8Array.from( | ||
[ | ||
...getUint8Array("n="), | ||
...getUint8Array(username), | ||
...getUint8Array(",r="), | ||
...nonce, | ||
], | ||
); | ||
} | ||
|
||
/** | ||
* @param input | ||
*/ | ||
function getUint8Array(input: string) { | ||
return new TextEncoder().encode(input); | ||
} | ||
|
||
export function cleanUsername(username: string) { | ||
return username.replace("=", "=3D").replace(",", "=2C"); | ||
} | ||
|
||
export function makeFirstMessage( | ||
credentials: { username: string }, | ||
nonce: Uint8Array, | ||
) { | ||
const username = cleanUsername(credentials.username); | ||
const mechanism = "SCRAM-SHA-1"; | ||
return { | ||
saslStart: 1, | ||
mechanism, | ||
autoAuthorize: 1, | ||
payload: new Binary( | ||
Uint8Array.from( | ||
[...getUint8Array("n,,"), ...clientFirstMessageBare(username, nonce)], | ||
), | ||
), | ||
options: { | ||
skipEmptyExchange: true, | ||
}, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { Credential, Document } from "../types.ts"; | ||
import { AuthPlugin } from "./base.ts"; | ||
|
||
export class ScramAuthPlugin extends AuthPlugin { | ||
prepare(credential: Credential): Document { | ||
const nonce = window.crypto.getRandomValues(new Uint8Array(24)); | ||
return { | ||
nonce, | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,11 @@ | ||
import { testWithClient } from "./common.ts"; | ||
|
||
testWithClient("createUser", async (client) => { | ||
const db = client.database("test"); | ||
await db.createUser("testUser", "testPassword"); | ||
}); | ||
// testWithClient("createUser", async (client) => { | ||
// const db = client.database("test"); | ||
// await db.createUser("testUser", "testPassword"); | ||
// }); | ||
|
||
testWithClient("dropUser", async (client) => { | ||
const db = client.database("test"); | ||
await db.dropUser("testUser"); | ||
}); | ||
// testWithClient("dropUser", async (client) => { | ||
// const db = client.database("test"); | ||
// await db.dropUser("testUser"); | ||
// }); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { assertEquals } from "../test.deps.ts"; | ||
import { HI } from "../../src/auth/mod.ts"; | ||
const salt = "rQ9ZY3MntBeuP3E1TDVC4w"; | ||
const inter = 10000; | ||
const data = "1c33006ec1ffd90f9cadcbcc0e118200"; | ||
Deno.test({ | ||
name: "HI", | ||
fn() { | ||
const saltedPassword = HI(data, salt, inter).toString("hex"); | ||
assertEquals(saltedPassword, "48549cb611401e7456e9072741898ea4006e4ee6"); | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
import { | ||
cleanUsername, | ||
clientFirstMessageBare, | ||
clientKeyFor, | ||
makeFirstMessage, | ||
nonceFor, | ||
passwordDigest, | ||
serverKeyFor, | ||
storedKeyFor, | ||
} from "../../src/auth/mod.ts"; | ||
import { assertEquals } from "../test.deps.ts"; | ||
import { Binary } from "../../bson/mod.ts"; | ||
|
||
interface PasswordValid { | ||
username: string; | ||
password: string; | ||
digest: string; | ||
} | ||
|
||
const passwordValdis: PasswordValid[] = [ | ||
{ | ||
username: "user", | ||
password: "pencil", | ||
digest: "1c33006ec1ffd90f9cadcbcc0e118200", | ||
}, | ||
{ | ||
username: "test", | ||
password: "test", | ||
digest: "a6de521abefc2fed4f5876855a3484f5", | ||
}, | ||
]; | ||
passwordValdis.forEach(({ username, password, digest }) => { | ||
Deno.test({ | ||
name: `passwordDigest:${username}:${password}`, | ||
fn() { | ||
const digestRes: string = passwordDigest(username, password); | ||
assertEquals(digestRes, digest); | ||
}, | ||
}); | ||
}); | ||
|
||
Deno.test({ | ||
name: "clientKey", | ||
fn() { | ||
const key: string = "48549cb611401e7456e9072741898ea4006e4ee6"; | ||
const expected = `6f7ca2af959e3b7823886dca969c04b166ed3b7d`; | ||
const result: string = clientKeyFor(key); | ||
assertEquals(expected, result); | ||
}, | ||
}); | ||
|
||
Deno.test({ | ||
name: "serverKey", | ||
fn() { | ||
const key: string = "48549cb611401e7456e9072741898ea4006e4ee6"; | ||
const expected: string = `550083f8dbe04acbb85a0081a6eacf1607b4835e`; | ||
const result: string = serverKeyFor(key); | ||
assertEquals(expected, result); | ||
}, | ||
}); | ||
|
||
Deno.test({ | ||
name: "storedKey", | ||
fn() { | ||
const data: string = "48549cb611401e7456e9072741898ea4006e4ee6"; | ||
const expected: string = "504ce7448255f3996b66ca99c09a6c5463d18dd7"; | ||
const result: string = storedKeyFor(data); | ||
assertEquals(expected, result); | ||
}, | ||
}); | ||
|
||
Deno.test({ | ||
name: "nonce", | ||
fn() { | ||
const buf = nonceFor(); | ||
assertEquals(buf.length, 24); | ||
}, | ||
}); | ||
|
||
Deno.test({ | ||
name: "clientFirstMessageBare", | ||
fn() { | ||
const username = "1234"; | ||
const nonce = new TextEncoder().encode("qwer"); | ||
const result: Uint8Array = clientFirstMessageBare(username, nonce); | ||
const expected: Uint8Array = Uint8Array.from( | ||
[110, 61, 49, 50, 51, 52, 44, 114, 61, 113, 119, 101, 114], | ||
); | ||
assertEquals(expected, result); | ||
}, | ||
}); | ||
|
||
Deno.test({ | ||
name: "cleanUsername", | ||
fn() { | ||
const username: string = "first=12,last=34"; | ||
const expected: string = "first=3D12=2Clast=34"; | ||
const result: string = cleanUsername(username); | ||
assertEquals(expected, result); | ||
}, | ||
}); | ||
|
||
function getUint8Array(str: string) { | ||
return new TextEncoder().encode(str); | ||
} | ||
|
||
Deno.test({ | ||
name: "makeFirstMessage", | ||
fn: function () { | ||
const username = "admin"; | ||
const credentials = { username }; | ||
const nonce = getUint8Array(username); | ||
const payload = new Binary( | ||
[ | ||
110, | ||
44, | ||
44, | ||
110, | ||
61, | ||
97, | ||
100, | ||
109, | ||
105, | ||
110, | ||
44, | ||
114, | ||
61, | ||
97, | ||
100, | ||
109, | ||
105, | ||
110, | ||
], | ||
); | ||
const expected = { | ||
saslStart: 1, | ||
mechanism: "SCRAM-SHA-1", | ||
payload, | ||
autoAuthorize: 1, | ||
options: { skipEmptyExchange: true }, | ||
}; | ||
const result = makeFirstMessage(credentials, nonce); | ||
assertEquals(expected, result); | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters