Skip to content
This repository was archived by the owner on Feb 26, 2020. It is now read-only.

Commit 2a635bd

Browse files
committed
Fixed JSON parsing.
1 parent 8cd9dc6 commit 2a635bd

6 files changed

Lines changed: 229 additions & 92 deletions

File tree

.settings/launch.json

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"version": "0.1.0",
3+
// List of configurations. Add new configurations or edit existing ones.
4+
// ONLY "node" and "mono" are supported, change "type" to switch.
5+
"configurations": [
6+
{
7+
// Name of configuration; appears in the launch configuration drop down menu.
8+
"name": "Launch server.js",
9+
// Type of configuration. Possible values: "node", "mono".
10+
"type": "node",
11+
// Workspace relative or absolute path to the program.
12+
"program": "server.js",
13+
// Automatically stop program after launch.
14+
"stopOnEntry": true,
15+
// Command line arguments passed to the program.
16+
"args": [],
17+
// Workspace relative or absolute path to the working directory of the program being debugged. Default is the current workspace.
18+
"cwd": ".",
19+
// Workspace relative or absolute path to the runtime executable to be used. Default is the runtime executable on the PATH.
20+
"runtimeExecutable": null,
21+
// Environment variables passed to the program.
22+
"env": { }
23+
},
24+
{
25+
"name": "Attach",
26+
"type": "node",
27+
// TCP/IP address. Default is "localhost".
28+
"address": "localhost",
29+
// Port to attach to.
30+
"port": 5858
31+
}
32+
]
33+
}

node-server/.settings/launch.json

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"version": "0.1.0",
3+
// List of configurations. Add new configurations or edit existing ones.
4+
// ONLY "node" and "mono" are supported, change "type" to switch.
5+
"configurations": [
6+
{
7+
// Name of configuration; appears in the launch configuration drop down menu.
8+
"name": "Launch server.js",
9+
// Type of configuration. Possible values: "node", "mono".
10+
"type": "node",
11+
// Workspace relative or absolute path to the program.
12+
"program": "server.js",
13+
// Automatically stop program after launch.
14+
"stopOnEntry": true,
15+
// Command line arguments passed to the program.
16+
"args": [],
17+
// Workspace relative or absolute path to the working directory of the program being debugged. Default is the current workspace.
18+
"cwd": ".",
19+
// Workspace relative or absolute path to the runtime executable to be used. Default is the runtime executable on the PATH.
20+
"runtimeExecutable": null,
21+
// Environment variables passed to the program.
22+
"env": { }
23+
},
24+
{
25+
"name": "Attach",
26+
"type": "node",
27+
// TCP/IP address. Default is "localhost".
28+
"address": "localhost",
29+
// Port to attach to.
30+
"port": 5858
31+
}
32+
]
33+
}

node-server/lib/metadata.js

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ var async = require('async');
2525
// Logging
2626

2727
var bunyan = require('bunyan');
28-
var log = bunyan.createLogger({name: 'Microsoft OpenID Connect Passport Strategy'});
28+
var log = bunyan.createLogger({name: 'Microsoft OpenID Connect: Passport Strategy: Metadata Parser'});
2929

3030
var Metadata = function (url, authtype) {
3131

@@ -40,7 +40,7 @@ var Metadata = function (url, authtype) {
4040
this.url = url;
4141
this.metadata = null;
4242
this.authtype = authtype;
43-
log.info(authtype, 'Metadata requested for authentication type');
43+
log.info('Metadata requested for authentication type', authtype);
4444
};
4545

4646
Object.defineProperty(Metadata, 'url', {
@@ -104,14 +104,13 @@ Metadata.prototype.updateOidcMetadata = function(doc, next) {
104104
try {
105105
this.oidc = {};
106106

107-
var issuer = doc['issuer'];
108-
var keyDescriptor = aadutils.getElement(idp[0], 'keys');
107+
this.oidc.issuer = doc['issuer'];
108+
this.oidc.keyURL = doc['jwks_uri'];
109+
this.oidc.algorithm = doc['id_token_signing_alg_values_supported'];
110+
111+
log.info("algorithm we will use is: ", this.oidc.algorithm);
112+
log.info("the Keys are located at: ", this.oidc.keyURL);
109113

110-
// copy the x509 certs from the metadata
111-
this.oidc.certs = [];
112-
for (var j=0;j<keyDescriptor.length;j++) {
113-
this.oidc.certs.push(keyDescriptor[j].KeyInfo[0].X509Data[0].X509Certificate[0]);
114-
}
115114
next(null);
116115
} catch (e) {
117116
next(new Error('Invalid Open ID Connect Federation Metadata ' + e.message));
@@ -160,12 +159,18 @@ Metadata.prototype.fetch = function(callback) {
160159
} else if(response.statusCode !== 200) {
161160
next(new Error("Error:" + response.statusCode + " Cannot get AAD Federation metadata from " + self.url));
162161
} else {
163-
log.info(body, "retreived");
162+
log.info("***********");
163+
log.info("");
164+
log.info(body);
165+
log.info("");
166+
log.info("***********");
164167
next(null, body);
165168
}
166169
});
167170
},
168171
function(body, next){
172+
173+
log.info("Parsing metadata for authtype: " + self.authtype);
169174
// parse the AAD Federation metadata xml
170175

171176
if(self.authtype == "saml" || self.authtype == "wsfed") {
@@ -177,34 +182,28 @@ Metadata.prototype.fetch = function(callback) {
177182
next(err);
178183

179184
});
180-
} else if(self.authtype == "oidc") {
181-
log.info(body, "Parsing JSON retreived from the endpoint");
182-
JSON.parse(body, function (err, data) {
183-
self.metatdata = data;
184-
next(err);
185-
});
186185

187-
} else {
188-
189-
next(new Error("Error: No Authentication type specified to metadata parser. Valid types are saml, wsfed, or odic"));
190-
}
186+
} else if(self.authtype == "oidc") {
187+
log.info("Parsing JSON retreived from the endpoint");
188+
self.metadata = JSON.parse(body);
191189

192-
},
190+
} else { next(new Error("No Authentication type specified to metadata parser. Valid types are saml, wsfed, or odic")); }
193191

192+
},
194193
function(next){
195-
if(self.authtype = "saml") {
194+
if(self.authtype == "saml") {
196195
// update the SAML SSO endpoints and certs from the metadata
197196
self.updateSamlMetadata(self.metatdata, next);
198197
}},
199198
function(next){
200-
if(self.authtype = "wsfed") {
199+
if(self.authtype == "wsfed") {
201200
// update the SAML SSO endpoints and certs from the metadata
202201
self.updateWsfedMetadata(self.metatdata, next);
203202
}},
204203
function(next){
205-
if(self.authtype = "oidc") {
204+
if(self.authtype == "oidc") {
206205
self.updateOidcMetadata(self.metadata, next);
207-
}},
206+
}}
208207
], function (err) {
209208
// return err or success (err === null) to callback
210209
callback(err);

node-server/lib/oidc_strategy.js

Lines changed: 93 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,56 @@ var jwt = require('jsonwebtoken');
2929
var request = require('request');
3030
var Metadata = require('./metadata').Metadata;
3131

32-
var log = bunyan.createLogger({name: 'Microsoft OpenID Connect Passport Strategy'});
32+
var log = bunyan.createLogger({name: 'Microsoft OpenID Connect: Passport Strategy'});
33+
/**
34+
* Applications must supply a `verify` callback, for which the function
35+
* signature is:
36+
*
37+
* function(token, done) { ... }
38+
*
39+
* `token` is the verified and decoded bearer token provided as a credential.
40+
* The verify callback is responsible for finding the user who posesses the
41+
* token, and invoking `done` with the following arguments:
42+
*
43+
* done(err, user, info);
44+
*
45+
* If the token is not valid, `user` should be set to `false` to indicate an
46+
* authentication failure. Additional token `info` can optionally be passed as
47+
* a third argument, which will be set by Passport at `req.authInfo`, where it
48+
* can be used by later middleware for access control. This is typically used
49+
* to pass any scope associated with the token.
50+
*
51+
* Options:
52+
*
53+
* - `realm` authentication realm, defaults to "Users"
54+
* - `scope` list of scope values indicating the required scope of the
55+
* access token for accessing the requested resource
56+
* - `audience` if you want to check JWT audience (aud), provide a value here
57+
* - `issuer` if you want to check JWT issuer (iss), provide a value here
58+
*
59+
* Examples:
60+
*
61+
* passport.use(new JwtBearerStrategy(
62+
* secretOrPublicKey
63+
* function(token, done) {
64+
* User.findById(token.sub, function (err, user) {
65+
* if (err) { return done(err); }
66+
* if (!user) { return done(null, false); }
67+
* return done(null, user, token);
68+
* });
69+
* }
70+
* ));
71+
*
72+
* For further details on HTTP Bearer authentication, refer to [The OAuth 2.0 Authorization Protocol: Bearer Tokens](http://tools.ietf.org/html/draft-ietf-oauth-v2-bearer)
73+
* For further details on JSON Web Token, refert to [JSON Web Token](http://tools.ietf.org/html/draft-ietf-oauth-json-web-token)
74+
*
75+
* @param {object} options - The Options.
76+
* @param {Function} verify - The verify callback.
77+
* @constructor
78+
*/
79+
80+
function Strategy(options, verify) {
3381

34-
function Strategy(options, callback, verify) {
3582

3683
// You can provide your own cert if you don't want to use Azure AD's certificate from our Identity servers (just in case you're using this for your own things!)
3784

@@ -42,7 +89,7 @@ if(options.publicCert) {
4289
if(options.metadataurl) {
4390

4491
log.info(options.metadataurl, 'metadata url provided to Strategy');
45-
this.metadata = new Metadata(options.metadataurl, "odic");
92+
this.metadata = new Metadata(options.metadataurl, "oidc");
4693
}
4794

4895
if (!options.certificate && !options.metadataurl) {
@@ -51,77 +98,82 @@ if (!options.certificate && !options.metadataurl) {
5198
}
5299

53100

54-
if (typeof callback == 'function') {
55-
verify = callback;
56-
// callback = {};
57-
}
58-
59101
// Passport requires a verify function
60102

61103
if (!verify) {
62104
throw new TypeError('OIDCBearerStrategy requires a verify callback. Do not cheat!');
63105
}
64106

65-
this.metadata.fetch(callback);
66-
log.info(this.metadata,'Metadata returned');
107+
this.certs = [];
67108

68-
function requestToUrl(callback) {
109+
// Token validation settings. Hopefully most of these will be pulled from the metadata and this is not needed
69110

70-
async.waterfall([
71-
function(next){
72-
if(!this.metadata.saml0) {
73-
this.metadata.fetch(next);
74-
} else {
75-
next(null);
76-
}
77-
target = "";
78-
console.log(this.metadata);
79-
}
80-
], function (err, target) {
81-
return callback(err, target);
82-
});
83-
}
84111

85112

113+
// fetch metadata
86114

115+
if(this.metadata) {
116+
this.metadata.fetch(function(err) {
117+
if(err) {
118+
log.warn('Error parsing metadata.', err);
119+
return err;
120+
} else {
121+
log.info(this.metadata,'Metadata returned');
122+
this.oidc = self.metadata.oidc;
123+
this.keyURL = oidc.keyURL;
124+
this.algothims = oidc.algorithm;
125+
}
126+
}); };
87127

128+
// fetch keys
88129

89130

90131

132+
var config = {
133+
// The URL of the metadata document for your app. We will put the keys for token validation from the URL found in the jwks_uri tag of the in the metadata.
134+
algorithms: this.algorithms
91135

136+
};
92137

93138
function jwtVerify(req, token, done) {
94139
if (!options.passReqToCallback) {
95140
token = arguments[0];
96141
done = arguments[1];
97142
req = null;
143+
log.info(token, 'was token going in to verification');
98144
}
99145

100-
requestToUrl(callback);
101-
// return pem.certToPEM(cert);
102-
var PEMkey = "";
103146

104-
jwt.verify(token, PEMkey, options, function (err, token) {
105-
if (err) {
106-
if (err instanceof jwt.TokenExpiredError) {
107-
log.warn('The access token provided to the server was expired');
108-
done(null, false, 'The access token expired');
109-
}
110-
else if (err instanceof jwt.JsonWebTokenError) {
111-
log.warn('Invalid token was provided to server: ' + err.message);
112-
done(null, false, util.format('Invalid token (%s)', err.message));
147+
148+
var PEMkey = pem.certToPEM(this._oidc.certs[0]);
149+
log.info(PEMkey, 'was the PEM returned');
150+
151+
jwt.verify(token, PEMkey, config, function (err, token) {
152+
if (err) {
153+
if (err instanceof jwt.TokenExpiredError) {
154+
log.warn("Access token expired");
155+
done(null, false, 'The access token expired');
156+
}
157+
else if (err instanceof jwt.JsonWebTokenError) {
158+
log.warn("An error was received validating the token", err.message);
159+
done(null, false, util.format('Invalid token (%s)', err.message));
160+
}
161+
else {
162+
done(err, false);
163+
}
113164
}
165+
114166
else {
115-
done(err, false);
116-
}
117-
} else {
167+
log.info(token, 'was token going out of verification');
118168
if (options.passReqToCallback) {
169+
log.info("We did pass Req back to Callback")
119170
verify(req, token, done);
120171
} else {
172+
log.info("We did not pass Req back to Callback")
121173
verify(token, done);
122174
}
123175
}
124-
});
176+
});
125177
}
126178

127179

node-server/lib/validator.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
// Logging
2323

2424
var bunyan = require('bunyan');
25-
var log = bunyan.createLogger({name: 'Microsoft OpenID Connect Passport Strategy'});
25+
var log = bunyan.createLogger({name: 'Microsoft OpenID Connect Passport Strategy Validator'});
2626

2727
var types = {};
2828

0 commit comments

Comments
 (0)