発生刷 |
ページ数 |
書籍改訂刷 |
電子書籍訂正 |
内容 |
登録日 |
1刷 |
059
真ん中のコード内下から2行目 |
3刷 |
済 |
誤 |
redirect_uri: client.redirect_urls[0] |
正 |
redirect_uri: client.redirect_uris[0] |
備
考 |
小文字の「l(エル)」を「i(アイ)に修正しました。
※リフローEPUBの場合は「3.2.1 認可リクエストの送信」の3番目のコードが該当します。 |
|
2020.01.07 |
1刷 |
061
一番下のコード内下から2行目 |
3刷 |
済 |
誤 |
redirect_uri: client.redirect_urls[0] |
正 |
redirect_uri: client.redirect_uris[0] |
備
考 |
小文字の「l(エル)」を「i(アイ)に修正しました。
※リフローEPUBの場合は「3.2.2 認可サーバーからのレスポンスの処理」の3番目のコードが該当します。 |
|
2020.01.07 |
1刷 |
064
3つ目のコードの1行目 |
3刷 |
済 |
誤 |
if (req.query.state == state) { |
正 |
if (req.query.state != state) { |
備
考 |
※リフローEPUBの場合は、「3.2.3 stateパラメータを使ったサイトをまたいだ攻撃に対する保護の追加」の3番目のコードが該当します。 |
|
2020.01.24 |
1刷 |
067
2つ目のコード 下から4行目 |
5刷 |
済 |
誤 |
res.ender('error', { error: 'Server returned response code: ' + |
正 |
res.render('error', {error: 'Server returned response code: ' + |
備
考 |
※リフローEPUBの場合、図3.5の後にある2つ目のコードが該当箇所になります。 |
|
2021.07.28 |
1刷 |
080
4.2節 1番目のコードブロック |
未 |
未 |
誤 |
nosql.one(function(token) {
if (token.access_token == inToken) {
return token;
}
}, function(err, token) {
if (token) {
console.log("We found a matching token: %s", inToken);
} else {
console.log(’No matching token was found.’);
}
req.access_token = token;
next();
return;
});
|
正 |
nosql.one().make(function(builder) {
builder.where('access_token', inToken);
builder.callback(function(err, token) {
if (token) {
console.log("We found a matching token: %s", inToken);
} else {
console.log('No matching token was found.');
};
req.access_token = token;
next();
return;
});
});
|
|
2024.09.04 |
1刷 |
100
5.1節 2番目のコードブロック(2行目の「`_.find`」が「`__.find`」になります) |
未 |
未 |
誤 |
var getClient = function(clientId) {
return _.find(clients, function(client) {
return client.client_id == clientId;
});
};
|
正 |
var getClient = function(clientId) {
return __.find(clients, function(client) {
return client.client_id == clientId;
});
};
|
|
2024.09.04 |
1刷 |
102
最初のコードブロック内のres.renderの第一引数
|
5刷 |
済 |
誤 |
if (!client) {
res.render('error, {error: 'Unknown client'});
…… |
正 |
if (!client) {
res.render('error', {error: 'Unknown client'});
…… |
備
考 |
「'error,」を「'error', 」に修正します。
※リフローEPUBの場合、「5.2.1 認可エンドポイント」の3番目のコードが該当箇所になります。 |
|
2022.10.20 |
1刷 |
105
1つ目のコード内、下から1行目 |
3刷 |
済 |
誤 |
reqid=tKVUYQSM}&approve=Approve |
正 |
reqid=tKVUYQSM&approve=Approve |
備
考 |
不要な } を削除しました。
※リフローEPUBの場合は、「5.2.2 クライアントの認可」の2番目のコードが該当します。 |
|
2019.05.07 |
1刷 |
112
囲み内の見出し、下から4行目 |
5刷 |
済 |
誤 |
見出し
トークンの中に何を待たせるのか?
下から4行目
OAuth のトークンは JWT(JASON Web Token)や…… |
正 |
見出し
トークンの中に何を持たせるのか?
下から4行目
OAuth のトークンは JWT(JSON Web Token)や…… |
備
考 |
内容を更新しました(2023/02/01).
※リフローEPUBの場合、「5.3.2 認可付与のリクエストに関する処理」のコラムの見出しと本文の2番目の段落が該当箇所になります。 |
|
2022.10.20 |
1刷 |
115
5.4節 2番目のコードブロック |
未 |
未 |
誤 |
nosql.one(function(token) {
if (token.refresh_token == req.body.refresh_token) {
return token;
}
}, function(err, token) {
if (token) {
対象のリフレッシュ・トークンが存在する場合の処理を行う
} else {
res.status(400).json({error: 'invalid_grant'});
return;
}
});
|
正 |
nosql.one().make(function(builder) {
builder.where('refresh_token', req.body.refresh_token);
builder.callback(function(err, token) {
if (token) {
対象のリフレッシュ・トークンが存在する場合の処理を行う
} else {
res.status(400).json({error: 'invalid_grant'});
return;
}
});
});
|
|
2024.09.04 |
1刷 |
115
5.4節 3番目のコードブロック |
未 |
未 |
誤 |
if (token.client_id != clientId) {
nosql.remove(function(found) {
return (found == token);
}, function () {} );
res.status(400).json({error: 'invalid_grant'});
return;
}
|
正 |
if (token.client_id != clientId) {
nosql.remove().make(function(builder) {
builder.where('refresh_token', req.body.refresh_token);
});
res.status(400).json({error: 'invalid_grant'});
return;
}
|
|
2024.09.04 |
1刷 |
130
ページ下部のコード |
5刷 |
済 |
誤 |
nosql.insert({
access_token: access_token,
client_id: client.clientId,
…… |
正 |
nosql.insert({
access_token: access_token,
client_id: client.client_id,
…… |
備
考 |
※リフローEPUBの場合、「6.1.1 インプリシット付与方式」の6番目のコードが該当箇所になります。 |
|
2022.10.26 |
1刷 |
135
上のコード |
5刷 |
済 |
誤 |
nosql.insert({
access_token: access_token,
client_id: client.clientId,
scope: rscope
});
|
正 |
nosql.insert({
access_token: access_token,
client_id: clientId,
scope: rscope
});
|
備
考 |
※リフローEPUBの場合「6.1.2 クライアント・クレデンシャルによる付与方式」の2番目のコラム「スコープと付与方式(Grant Type)のすぐ上にあるコードが該当箇所になります。 |
|
2022.11.01 |
1刷 |
139
1つ目のコード内、最下行 |
2刷 |
済 |
誤 |
grant_type=password}&scope=foo%20bar&username=alice&password=secret |
正 |
grant_type=password&scope=foo%20bar&username=alice&password=secret |
備
考 |
不要な } を削除しました。
※リフローEPUBの場合は、「6.1.3 リソース所有者のクレデンシャルによる付与方式」の1番目のコードが該当します。 |
|
2019.02.19 |
1刷 |
140
2つ目のコード、上から3行目 |
3刷 |
済 |
誤 |
if (user) |
正 |
if (!user) { |
備
考 |
※リフローEPUBの場合は、「6.1.3 リソース所有者のクレデンシャルによる付与方式」の5番目のコードが該当します。 |
|
2019.05.07 |
1刷 |
140
3番目のコード、上から2行目 |
3刷 |
済 |
誤 |
if (user.password = password) |
正 |
if (user.password != password) { |
備
考 |
!=の間違い。
※リフローEPUBの場合は、「6.1.3 リソース所有者のクレデンシャルによる付与方式」の6番目のコードが該当します。 |
|
2019.05.07 |
1刷 |
141
上から2つ目のコード |
5刷 |
済 |
誤 |
nosql.insert({
access_token: access_token,
client_id: client.clientId,
scope: rscope
});
nosql.insert({
refresh_token: refresh_token,
client_id: client.clientId,
scope: rscope
});
|
正 |
nosql.insert({
access_token: access_token,
client_id: clientId,
scope: rscope
});
nosql.insert({
refresh_token: refresh_token,
client_id: clientId,
scope: rscope
});
|
備
考 |
※リフローEPUBでは、「6.1.3 リソース所有者のクレデンシャルによる付与方式」の図6.4の上にあるコードが該当箇所になります。 |
|
2022.11.01 |
1刷 |
142
本文上から1行目 |
3刷 |
済 |
誤 |
クトを生成しています。 |
正 |
成しています。 |
備
考 |
※リフローEPUBの場合、「6.1.3 リソース所有者のクレデンシャルによる付与方式」の8番目のコードの直後の段落が該当します。 |
|
2019.05.07 |
1刷 |
151
コード内、下から6行目 |
3刷 |
済 |
誤 |
if (callbackData.state == localStorage.getItem('oauth-state')) |
正 |
if (callbackData.state !== localStorage.getItem('oauth-state')) { |
備
考 |
※リフローEPUBの場合、「6.2.2 ブラウザ内アプリケーション」の4番目のコードが該当します。 |
|
2019.05.07 |
1刷 |
172
7.3節 3番目のコードブロック |
未 |
未 |
誤 |
function handleAuthorizationRequestClick(ev) {
if (!client.client_id) {
$.ajax({
url: authServer.registrationEndpoint,
type: 'POST',
data: client,
crossDomain: true,
dataType: ’json’
}).done(function(data) {
client.client_id = data.client_id;
client.client_secret = data.client_secret;
}).fail(function() {
$('.oauth-protected-resource')
.text('Error while fetching registration endpoint');
});
} else { …略
|
正 |
var protectedResource = 'http://localhost:9002/resource';
window.onload = function() {
if (!client.client_id) {
$.ajax({
url: authServer.registrationEndpoint,
type: 'POST',
data: client,
crossDomain: true,
dataType: 'json'
}).done(function(data) {
client.client_id = data.client_id;
client.client_secret = data.client_secret;
}).fail(function() {
$('.oauth-protected-resource')
.text('Error while fetching registration endpoint');
});
}
}
|
|
2024.09.04 |
1刷 |
237,238
10.4節 2番目のコードブロック |
未 |
未 |
誤 |
var form_data = qs.stringify({
grant_type: 'authorization_code',
code: code,
redirect_uri: client.redirect_uris[0],
code_veryfier: code_veryfier
});
|
正 |
var form_data = qs.stringify({
grant_type: 'authorization_code',
code: code,
redirect_uri: client.redirect_uri,
code_verifier: code_verifier
});
|
|
2024.09.04 |
1刷 |
257
11.3節 1番目のコードブロック |
未 |
未 |
誤 |
// 先ほどまでのすべての整合性チェックはこのif文内で行われる
if (jose.jws.JWS.verify(
inToken,
new Buffer(sharedTokenSecret).toString(’hex’),
[header.alg])) {
…略
}
|
正 |
// 先ほどまでのすべての整合性チェックはこのif文内で行われる
if (jose.jws.JWS.verify(
inToken,
Buffer.from(sharedTokenSecret).toString('hex'),
[header.alg])) {
…略
}
|
|
2024.09.04 |
1刷 |
268
11.4節 1番目のコードブロック |
未 |
未 |
誤 |
var inToken = req.body.token;
nosql.one(function(token) {
if (token.access_token == inToken) {
return token;
}
}, function(err, token) {
if (token) {
var introspectionResponse = {
active: true,
iss: 'http://localhost:9001/',
aud: 'http://localhost:9002/',
sub: token.user ? token.user.sub : undefined,
username: token.user ? token.user.preferred_username : undefined,
scope: token.scope ? token.scope.join(’ ’) : undefined,
client_id: token.client_id
};
res.status(200).json(introspectionResponse);
return;
} else {
var introspectionResponse = {
active: false
};
res.status(200).json(introspectionResponse);
return;
}
});
|
正 |
var inToken = req.body.token;
console.log('Introspecting token %s', inToken);
nosql.one().make(function(builder) {
builder.where('access_token', inToken);
builder.callback(function(err, token) {
if (token) {
var introspectionResponse = {
active: true,
iss: 'http://localhost:9001/',
aud: 'http://localhost:9002/',
sub: token.user ? token.user.sub : undefined,
username: token.user ? token.user.preferred_username : undefined,
scope: token.scope ? token.scope.join(' ') : undefined,
client_id: token.client_id
};
res.status(200).json(introspectionResponse);
return;
} else {
var introspectionResponse = {
active: false
};
res.status(200).json(introspectionResponse);
return;
}
});
});
|
|
2024.09.04 |
1刷 |
274,275
11.5節 2番目のコードブロック |
未 |
未 |
誤 |
var inToken = req.body.token;
nosql.remove(function(token) {
if (token.access_token == inToken &&
token.client_id == clientId) {
return true;
}
}, function(err, count) {
res.status(204).end();
return;
});
|
正 |
var inToken = req.body.token;
nosql.remove().make(function(builder) {
builder.and();
builder.where('access_token', inToken);
builder.where('client_id', clientId);
builder.callback(function(err, count) {
console.log("Removed %s tokens", count);
res.status(204).end();
return;
});
});
|
|
2024.09.04 |
1刷 |
313
12.4節 3番目のコードブロック |
未 |
未 |
誤 |
nosql.remove(function(token) {
if (token.client_id == req.client.client_id) {
return true;
}
}, function(err, count) {
console.log("Removed %s clients", count);
});
res.status( 204).end();
return;
|
正 |
nosql.remove().make(function(builder) {
builder.where('client_id', clientId);
builder.callback(function(err, count) {
console.log("Removed %s tokens", count);
});
});
res.status(204).end();
return;
|
|
2024.09.04 |
1刷 |
324
上から4行目 |
2刷 |
済 |
誤 |
ここでは認可サーバーとリソース所有者をまとめて、それをひとつの構成要素であるアイデンティティ・プロバイダとして見ていきます。 |
正 |
ここでは認可サーバーと保護対象リソースをまとめて、それをひとつの構成要素であるアイデンティティ・プロバイダとして見ていきます。 |
備
考 |
※リフローEPUBでは、図13.2のすぐ上の段落が該当箇所になります。 |
|
2019.02.19 |
1刷 |
410,411
付録A 2番目のコードブロック |
未 |
未 |
誤 |
> node -v
v4.4.1
> npm -v
2.15.1 |
正 |
> node -v
v14.13.1
> npm -v
6.14.8 |
|
2024.09.04 |
1刷 |
420,421
付録B リストB.6 |
未 |
未 |
誤 |
var getAccessToken = function(req, res, next) {
var inToken = null;
var auth = req.headers[’authorization’];
if (auth && auth.toLowerCase().indexOf(’bearer’) == 0) {
inToken = auth.slice(’bearer ’.length);
} else if (req.body && req.body.access_token) {
inToken = req.body.access_token;
} else if (req.query && req.query.access_token) {
inToken = req.query.access_token
}
console.log(’Incoming token: %s’, inToken);
nosql.one(function(token) {
if (token.access_token == inToken) {
return token;
}
}, function(err, token) {
if (token) {
console.log("We found a matching token: %s", inToken);
} else {
console.log(’No matching token was found.’);
}
req.access_token = token;
next();
return;
});
};
|
正 |
var getAccessToken = function(req, res, next) {
var inToken = null;
var auth = req.headers['authorization'];
if (auth && auth.toLowerCase().indexOf('bearer') == 0) {
inToken = auth.slice('bearer '.length);
} else if (req.body && req.body.access_token) {
inToken = req.body.access_token;
} else if (req.query && req.query.access_token) {
inToken = req.query.access_token
}
console.log('Incoming token: %s', inToken);
nosql.one().make(function(builder) {
builder.where('access_token', inToken);
builder.callback(function(err, token) {
if (token) {
console.log("We found a matching token: %s", inToken);
} else {
console.log('No matching token was found.');
};
req.access_token = token;
next();
return;
});
});
};
|
|
2024.09.04 |
1刷 |
424,425
付録B リストB.10 |
未 |
未 |
誤 |
} else if (req.body.grant_type == ’refresh_token’) {
nosql.one(function(token) {
if (token.refresh_token == req.body.refresh_token) {
return token;
}
}, function(err, token) {
if (token) {
console.log("We found a matching refresh token: %s",
req.body.refresh_token);
if (token.client_id != clientId) {
nosql.remove(function(found) {
return (found == token);
}, function () {} );
res.status(400).json({error: ’invalid_grant’});
return;
}
var access_token = randomstring.generate();
nosql.insert({
access_token: access_token,
client_id: clientId
});
var token_response = {
access_token: access_token,
token_type: ’Bearer’,
refresh_token: token.refresh_token
};
res.status(200).json(token_response);
return;
} else {
console.log(’No matching token was found.’);
res.status(400).json({error: ’invalid_grant’});
return;
}
});
}
|
正 |
} else if (req.body.grant_type == 'refresh_token') {
nosql.one().make(function(builder) {
builder.where('refresh_token', req.body.refresh_token);
builder.callback(function(err, token) {
if (token) {
console.log("We found a matching refresh token: %s",
req.body.refresh_token);
if (token.client_id != clientId) {
nosql.remove().make(function(builder) {
builder.where('refresh_token', req.body.refresh_token);
});
res.status(400).json({error: 'invalid_grant'});
return;
}
var access_token = randomstring.generate();
nosql.insert({
access_token: access_token,
client_id: clientId
});
var token_response = {
access_token: access_token,
token_type: 'Bearer',
refresh_token: token.refresh_token
};
res.status(200).json(token_response);
return;
} else {
console.log('No matching token was found.');
res.status(400).json({error: 'invalid_grant'});
return;
}
});
});
} else if …略
|
|
2024.09.04 |
1刷 |
425
付録B リストB.11 |
未 |
未 |
誤 |
app.post(’/introspect’, function(req, res) {
var auth = req.headers[’authorization’];
var resourceCredentials = decodeClientCredentials(auth);
var resourceId = resourceCredentials.id;
var resourceSecret = resourceCredentials.secret;
var resource = getProtectedResource(resourceId);
if (!resource) {
console.log(’Unknown resource %s’, resourceId);
res.status(401).end();
return;
}
if (resource.resource_secret != resourceSecret) {
console.log(’Mismatched secret, expected %s got %s’,
resource.resource_secret, resourceSecret);
res.status(401).end();
return;
}
var inToken = req.body.token;.
console.log(’Introspecting token %s’, inToken);
nosql.one(function(token) {
if (token.access_token == inToken) {
return token;
}
}, function(err, token) {
if (token) {
console.log("We found a matching token: %s", inToken);
var introspectionResponse = {
active: true,
iss: ’http://localhost:9001/’,
aud: ’http://localhost:9002/’,
sub: token.user ? token.user.sub : undefined,
username: token.user ? token.user.preferred_username :
undefined,
scope: token.scope ? token.scope.join(’ ’) : undefined,
client_id: token.client_id
};
res.status(200).json(introspectionResponse);
return;
} else {
console.log(’No matching token was found.’);
var introspectionResponse = {
active: false
};
res.status(200).json(introspectionResponse);
return;
}
});
});
|
正 |
app.post('/introspect', function(req, res) {
var auth = req.headers['authorization'];
var resourceCredentials = decodeClientCredentials(auth);
var resourceId = resourceCredentials.id;
var resourceSecret = resourceCredentials.secret;
var resource = getProtectedResource(resourceId);
if (!resource) {
console.log('Unknown resource %s', resourceId);
res.status(401).end();
return;
}
if (resource.resource_secret != resourceSecret) {
console.log('Mismatched secret, expected %s got %s',
resource.resource_secret, resourceSecret);
res.status(401).end();
return;
}
var inToken = req.body.token;
console.log('Introspecting token %s', inToken);
nosql.one().make(function(builder) {
builder.where('access_token', inToken);
builder.callback(function(err, token) {
if (token) {
console.log("We found a matching token: %s", inToken);
var introspectionResponse = {
active: true,
iss: 'http://localhost:9001/',
aud: 'http://localhost:9002/',
sub: token.user ? token.user.sub : undefined,
username: token.user ? token.user.preferred_username : undefined,
scope: token.scope ? token.scope.join(' ') : undefined,
client_id: token.client_id
};
res.status(200).json(introspectionResponse);
return;
} else {
console.log('No matching token was found.');
var introspectionResponse = {
active: false
};
res.status(200).json(introspectionResponse);
return;
}
});
});
});
|
|
2024.09.04 |
1刷 |
426,427
付録B リストB.12 |
未 |
未 |
誤 |
app.post(’/revoke’, function(req, res) {
var auth = req.headers[’authorization’];
if (auth) {
// Authorizationヘッダーをチェック
var clientCredentials = decodeClientCredentials(auth);
var clientId = clientCredentials.id;
var clientSecret = clientCredentials.secret;
}
// ない場合はPOST送信されたボディーをチェック
if (req.body.client_id) {
if (clientId) {
// すでにAuthorizationヘッダーにクライアントのクレデンシャルがある場合はエラー
console.log(’Client attempted to authenticate with multiple methods’);
res.status(401).json({error: ’invalid_client’});
return;
}
var clientId = req.body.client_id;
var clientSecret = req.body.client_secret;
}
var client = getClient(clientId);
if (!client) {
console.log(’Unknown client %s’, clientId);
res.status(401).json({error: ’invalid_client’});
return;
}
if (client.client_secret != clientSecret) {
console.log(’Mismatched client secret, expected %s got %s’,
client.client_secret, clientSecret);
res.status(401).json({error: ’invalid_client’});
return;
}
var inToken = req.body.token;
nosql.remove(function(token) {
if (token.access_token == inToken && token.client_id == clientId) {
return true;
}
}, function(err, count) {
console.log("Removed %s tokens", count);
res.status(204).end();
return;
});
});
|
正 |
app.post('/revoke', function(req, res) {
var auth = req.headers['authorization'];
if (auth) {
// Authorizationヘッダーをチェック
var clientCredentials = decodeClientCredentials(auth);
var clientId = clientCredentials.id;
var clientSecret = clientCredentials.secret;
}
// ない場合はPOST送信されたボディーをチェック
if (req.body.client_id) {
if (clientId) {
// すでにAuthorizationヘッダーにクライアントのクレデンシャルがある場合はエラー
console.log('Client attempted to authenticate with multiplemethods');
res.status(401).json({error: 'invalid_client'});
return;
}
var clientId = req.body.client_id;
var clientSecret = req.body.client_secret;
}
var client = getClient(clientId);
if (!client) {
console.log('Unknown client %s', clientId);
res.status(401).json({error: 'invalid_client'});
return;
}
if (client.client_secret != clientSecret) {
console.log('Mismatched client secret, expected %s got %s',
client.client_secret, clientSecret);
res.status(401).json({error: 'invalid_client'});
return;
}
var inToken = req.body.token;
nosql.remove().make(function(builder) {
builder.and();
builder.where('access_token', inToken);
builder.where('client_id', clientId);
builder.callback(function(err, count) {
console.log("Removed %s tokens", count);
res.status(204).end();
return;
});
});
});
|
|
2024.09.04 |