Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
P
persona
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Wiki
Code
Merge requests
0
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Hexang 息壤平台
persona
Commits
2a342400
Commit
2a342400
authored
13 years ago
by
Lloyd Hilaiel
Browse files
Options
Downloads
Patches
Plain Diff
teach the verifier how to verify assertions issued by primaries
parent
3f0fdf2a
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
lib/primary.js
+11
-4
11 additions, 4 deletions
lib/primary.js
lib/verifier/certassertion.js
+31
-3
31 additions, 3 deletions
lib/verifier/certassertion.js
tests/verifier-test.js
+84
-5
84 additions, 5 deletions
tests/verifier-test.js
with
126 additions
and
12 deletions
lib/primary.js
+
11
−
4
View file @
2a342400
...
...
@@ -173,6 +173,15 @@ if (process.env['SHIMMED_PRIMARIES']) {
});
}
exports
.
getPublicKey
=
function
(
domain
,
cb
)
{
exports
.
checkSupport
(
domain
,
function
(
err
,
rv
)
{
if
(
err
)
return
cb
(
err
);
var
pubKey
=
g_cache
[
domain
].
publicKey
;
if
(
!
pubKey
)
return
cb
(
"
can't get public key for
"
+
domain
);
cb
(
null
,
pubKey
);
});
};
// verify an assertion generated to authenticate to browserid
exports
.
verifyAssertion
=
function
(
assertion
,
cb
)
{
try
{
...
...
@@ -188,10 +197,8 @@ exports.verifyAssertion = function(assertion, cb) {
if
(
issuer
===
config
.
get
(
'
hostname
'
))
{
cb
(
"
cannot authenticate to browserid with a certificate issued by it.
"
);
}
else
{
exports
.
checkSupport
(
issuer
,
function
(
err
,
rv
)
{
exports
.
getPublicKey
(
issuer
,
function
(
err
,
pubKey
)
{
if
(
err
)
return
cb
(
err
);
var
pubKey
=
g_cache
[
issuer
].
publicKey
;
if
(
!
pubKey
)
return
cb
(
"
can't get public key for
"
+
issuer
);
next
(
pubKey
);
});
}
...
...
@@ -213,4 +220,4 @@ exports.verifyAssertion = function(assertion, cb) {
cb
(
"
can't verify assertion:
"
+
e
.
toString
());
}
},
cb
);
};
\ No newline at end of file
};
This diff is collapsed.
Click to expand it.
lib/verifier/certassertion.js
+
31
−
3
View file @
2a342400
...
...
@@ -47,7 +47,8 @@ jwcert = require("jwcrypto/jwcert"),
vep
=
require
(
"
jwcrypto/vep
"
),
config
=
require
(
"
../configuration.js
"
),
logger
=
require
(
"
../logging.js
"
).
logger
,
secrets
=
require
(
'
../secrets.js
'
);
secrets
=
require
(
'
../secrets.js
'
),
primary
=
require
(
'
../primary.js
'
);
try
{
const
publicKey
=
secrets
.
loadPublicKey
();
...
...
@@ -126,12 +127,29 @@ function verify(assertion, audience, successCB, errorCB) {
return
errorCB
(
"
malformed assertion
"
);
}
var
ultimateIssuer
;
jwcert
.
JWCert
.
verifyChain
(
bundle
.
certificates
,
new
Date
(),
function
(
issuer
,
next
)
{
// update issuer with each issuer in the chain, so the
// returned issuer will be the last cert in the chain
ultimateIssuer
=
issuer
;
// allow other retrievers for testing
if
(
issuer
===
config
.
get
(
'
hostname
'
))
return
next
(
publicKey
);
return
errorCB
(
"
this verifier doesn't respect certs issued from domains other than:
"
+
config
.
get
(
'
hostname
'
));
// XXX: this network work happening inside a compute process.
// if we have a large number of requests to auth assertions that require
// keyfetch, this could theoretically hurt our throughput. We could
// move the fetch up into the browserid process and pass it into the
// compute process at some point.
// let's go fetch the public key for this host
primary
.
getPublicKey
(
issuer
,
function
(
err
,
pubKey
)
{
if
(
err
)
return
errorCB
(
err
);
next
(
pubKey
);
});
},
function
(
pk
,
principal
)
{
var
tok
=
new
jwt
.
JWT
();
tok
.
parse
(
bundle
.
assertion
);
...
...
@@ -144,8 +162,18 @@ function verify(assertion, audience, successCB, errorCB) {
return
errorCB
(
"
audience mismatch:
"
+
err
);
}
// verify that the issuer is the same as the email domain
// NOTE: for "delegation of authority" support we'll need to make this check
// more sophisticated
var
domainFromEmail
=
principal
.
email
.
replace
(
/^.*@/
,
''
);
if
(
ultimateIssuer
!=
config
.
get
(
'
hostname
'
)
&&
ultimateIssuer
!==
domainFromEmail
)
{
return
errorCB
(
"
issuer issue '
"
+
ultimateIssuer
+
"
' may not speak for emails from '
"
+
domainFromEmail
+
"
'
"
);
}
if
(
tok
.
verify
(
pk
))
{
successCB
(
principal
.
email
,
tok
.
audience
,
tok
.
expires
,
config
.
get
(
'
hostname
'
)
);
successCB
(
principal
.
email
,
tok
.
audience
,
tok
.
expires
,
ultimateIssuer
);
}
else
{
errorCB
(
"
verification failure
"
);
}
...
...
This diff is collapsed.
Click to expand it.
tests/verifier-test.js
+
84
−
5
View file @
2a342400
...
...
@@ -49,7 +49,8 @@ jwt = require('jwcrypto/jwt.js'),
vep
=
require
(
'
jwcrypto/vep.js
'
),
jwcert
=
require
(
'
jwcrypto/jwcert.js
'
),
http
=
require
(
'
http
'
),
querystring
=
require
(
'
querystring
'
);
querystring
=
require
(
'
querystring
'
),
path
=
require
(
'
path
'
);
var
suite
=
vows
.
describe
(
'
verifier
'
);
...
...
@@ -657,10 +658,10 @@ suite.addBatch({
}
});
// now verify that
no-one other than browserid is allowed to issue assertions
//
(until primary support is implemented)
// now verify that
assertions from a primary who does not have browserid support
//
will fail to verify
suite
.
addBatch
({
"
generating an assertion from a cert signed by
some other domain
"
:
{
"
generating an assertion from a cert signed by
a bogus primary
"
:
{
topic
:
function
()
{
var
fakeDomainKeypair
=
jwk
.
KeyPair
.
generate
(
"
RS
"
,
64
);
var
newClientKeypair
=
jwk
.
KeyPair
.
generate
(
"
DS
"
,
256
);
...
...
@@ -686,7 +687,85 @@ suite.addBatch({
"
to return a clear error message
"
:
function
(
r
,
err
)
{
var
resp
=
JSON
.
parse
(
r
.
body
);
assert
.
strictEqual
(
resp
.
status
,
'
failure
'
);
assert
.
strictEqual
(
resp
.
reason
,
"
this verifier doesn't respect certs issued from domains other than: 127.0.0.1
"
);
assert
.
strictEqual
(
resp
.
reason
,
"
can't get public key for otherdomain.tld
"
);
}
}
}
});
// now verify that assertions from a primary who does have browserid support
// but has no authority to speak for an email address will fail
suite
.
addBatch
({
"
generating an assertion from a cert signed by a real (simulated) primary
"
:
{
topic
:
function
()
{
var
secretKey
=
jwk
.
SecretKey
.
fromSimpleObject
(
JSON
.
parse
(
require
(
'
fs
'
).
readFileSync
(
path
.
join
(
__dirname
,
'
..
'
,
'
example
'
,
'
primary
'
,
'
sample.privatekey
'
))));
var
newClientKeypair
=
jwk
.
KeyPair
.
generate
(
"
DS
"
,
256
);
expiration
=
new
Date
(
new
Date
().
getTime
()
+
(
1000
*
60
*
60
*
6
));
var
cert
=
new
jwcert
.
JWCert
(
"
example.domain
"
,
expiration
,
new
Date
(),
newClientKeypair
.
publicKey
,
{
email
:
TEST_EMAIL
}).
sign
(
secretKey
);
var
expirationDate
=
new
Date
(
new
Date
().
getTime
()
+
(
2
*
60
*
1000
));
var
tok
=
new
jwt
.
JWT
(
null
,
expirationDate
,
TEST_ORIGIN
);
return
vep
.
bundleCertsAndAssertion
([
cert
],
tok
.
sign
(
newClientKeypair
.
secretKey
));
},
"
yields a good looking assertion
"
:
function
(
r
,
err
)
{
assert
.
isString
(
r
);
assert
.
equal
(
r
.
length
>
0
,
true
);
},
"
will cause the verifier
"
:
{
topic
:
function
(
assertion
)
{
wsapi
.
post
(
'
/verify
'
,
{
audience
:
TEST_ORIGIN
,
assertion
:
assertion
}).
call
(
this
);
},
"
to return a clear error message
"
:
function
(
r
,
err
)
{
var
resp
=
JSON
.
parse
(
r
.
body
);
assert
.
strictEqual
(
resp
.
status
,
'
failure
'
);
assert
.
strictEqual
(
resp
.
reason
,
"
issuer issue 'example.domain' may not speak for emails from 'somedomain.com'
"
);
}
}
}
});
// now verify that assertions from a primary who does have browserid support
// and may speak for an email address will succeed
suite
.
addBatch
({
"
generating an assertion from a cert signed by a real (simulated) primary
"
:
{
topic
:
function
()
{
var
secretKey
=
jwk
.
SecretKey
.
fromSimpleObject
(
JSON
.
parse
(
require
(
'
fs
'
).
readFileSync
(
path
.
join
(
__dirname
,
'
..
'
,
'
example
'
,
'
primary
'
,
'
sample.privatekey
'
))));
var
newClientKeypair
=
jwk
.
KeyPair
.
generate
(
"
DS
"
,
256
);
expiration
=
new
Date
(
new
Date
().
getTime
()
+
(
1000
*
60
*
60
*
6
));
var
cert
=
new
jwcert
.
JWCert
(
"
example.domain
"
,
expiration
,
new
Date
(),
newClientKeypair
.
publicKey
,
{
email
:
"
foo@example.domain
"
}).
sign
(
secretKey
);
var
expirationDate
=
new
Date
(
new
Date
().
getTime
()
+
(
2
*
60
*
1000
));
var
tok
=
new
jwt
.
JWT
(
null
,
expirationDate
,
TEST_ORIGIN
);
return
vep
.
bundleCertsAndAssertion
([
cert
],
tok
.
sign
(
newClientKeypair
.
secretKey
));
},
"
yields a good looking assertion
"
:
function
(
r
,
err
)
{
assert
.
isString
(
r
);
assert
.
equal
(
r
.
length
>
0
,
true
);
},
"
will cause the verifier
"
:
{
topic
:
function
(
assertion
)
{
wsapi
.
post
(
'
/verify
'
,
{
audience
:
TEST_ORIGIN
,
assertion
:
assertion
}).
call
(
this
);
},
"
to return a clear error message
"
:
function
(
r
,
err
)
{
var
resp
=
JSON
.
parse
(
r
.
body
);
assert
.
strictEqual
(
resp
.
status
,
'
okay
'
);
assert
.
strictEqual
(
resp
.
issuer
,
"
example.domain
"
);
assert
.
strictEqual
(
resp
.
audience
,
TEST_ORIGIN
);
assert
.
strictEqual
(
resp
.
email
,
"
foo@example.domain
"
);
}
}
}
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment