Before posts about Hydra get access token is use golang HydraOauthConfig.Exchange(ctx, code). This is easy way. But on front website like vue or other framework how to get access token.
Use adminer test maraidb: http://192.168.99.100:8080 root/secret
mariadb init
DROP DATABASE IF EXISTS `openid`;
CREATE DATABASE `openid` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */;
USE `openid`;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` text COLLATE utf8mb4_unicode_ci NOT NULL,
`email` text COLLATE utf8mb4_unicode_ci NOT NULL,
`password` text COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `user` (`id`, `name`, `email`, `password`) VALUES
(1, 'foobar', 'foo@bar.com', '3858f62230ac3c915f300c664312c63f');
ory-hydra-login-consent modify package.json add
"md5": "^2.2.1",
"mysql": "^2.17.1"
ory-hydra-login-consent add db/database.js
var mysql = require('mysql');
var pool = mysql.createPool({
host : 'mariadb',
user : 'root',
password : 'secret',
database: 'openid'
});
var query=function(sql,options,callback){
pool.getConnection(function(err,conn){
pool.query
if(err){
callback(err,null,null);
}else{
conn.query(sql,options,function(err,results,fields){
//释放连接
conn.release();
//事件驱动回调
callback(err,results,fields);
});
}
});
};
module.exports = {query, pool}
ory-hydra-login-consent modify routes/login.js
...
router.post('/', csrfProtection, function (req, res, next) {
// The challenge is now a hidden input field, so let's take it from the request body instead
var challenge = req.body.challenge;
var sql = "select count(*) as count from user where email = ? and password = ?"
var params = [req.body.email, md5(req.body.password)]
//db.get(sql, params, (err, row) => {
pool.query(sql, params, (err, row) => {
if (err) {
res.status(400).json({"db error":err.message});
return;
}
if(!(row.count==1)){ //找不到
res.render('login', {
csrfToken: req.csrfToken(),
challenge: challenge,
error: 'The username / password combination is not correct'
});
return;
}
hydra.acceptLoginRequest(challenge, {
// Subject is an alias for user ID. A subject can be a random string, a UUID, an email address, ....
subject: req.body.email,
// This tells hydra to remember the browser and automatically authenticate the user in future requests. This will
// set the "skip" parameter in the other route to true on subsequent requests!
remember: Boolean(req.body.remember),
// When the session expires, in seconds. Set this to 0 so it will never expire.
remember_for: 3600,
// Sets which "level" (e.g. 2-factor authentication) of authentication the user has. The value is really arbitrary
// and optional. In the context of OpenID Connect, a value of 0 indicates the lowest authorization level.
// acr: '0',
})
.then(function (response) {
// All we need to do now is to redirect the user back to hydra!
res.redirect(response.redirect_to);
})
// This will handle any error that happens when making HTTP calls to hydra
.catch(function (error) {
next(error);
});
});
// Let's check if the user provided valid credentials. Of course, you'd use a database or some third-party service
// for this!
// if (!(req.body.email === 'foo@bar.com' && req.body.password === 'foobar')) {
// // Looks like the user provided invalid credentials, let's show the ui again...
// res.render('login', {
// csrfToken: req.csrfToken(),
// challenge: challenge,
// error: 'The username / password combination is not correct'
// });
// return;
// }
// Seems like the user authenticated! Let's tell hydra...
// hydra.acceptLoginRequest(challenge, {
// // Subject is an alias for user ID. A subject can be a random string, a UUID, an email address, ....
// subject: 'foo@bar.com',
// // This tells hydra to remember the browser and automatically authenticate the user in future requests. This will
// // set the "skip" parameter in the other route to true on subsequent requests!
// remember: Boolean(req.body.remember),
// // When the session expires, in seconds. Set this to 0 so it will never expire.
// remember_for: 3600,
// // Sets which "level" (e.g. 2-factor authentication) of authentication the user has. The value is really arbitrary
// // and optional. In the context of OpenID Connect, a value of 0 indicates the lowest authorization level.
// // acr: '0',
// })
// .then(function (response) {
// // All we need to do now is to redirect the user back to hydra!
// res.redirect(response.redirect_to);
// })
// // This will handle any error that happens when making HTTP calls to hydra
// .catch(function (error) {
// next(error);
// });
// You could also deny the login request which tells hydra that no one authenticated!
// hydra.rejectLoginRequest(challenge, {
// error: 'invalid_request',
// error_description: 'The user did something stupid...'
// })
// .then(function (response) {
// // All we need to do now is to redirect the browser back to hydra!
// res.redirect(response.redirect_to);
// })
// // This will handle any error that happens when making HTTP calls to hydra
// .catch(function (error) {
// next(error);
// });
});
https://t.tt:9010 When login id/pwd, can use adminer change database user email/password.
A permission allows an actor to perform a certain action in a system: Bob is allowed to delete his own photos.
OAuth 2.0 Scope implies that an end-user granted certain privileges to a client: Bob allowed the OAuth 2.0 Client to delete all users.
The OAuth 2.0 Scope can be granted without the end-user actually having the right permissions. In the examples above, Bob granted an OAuth 2.0 Client the permission ("scope") to delete all users in his name. However, since Bob is not an administrator, that permission ("access control") is not actually granted to Bob. Therefore any request by the OAuth 2.0 Client that tries to delete users on behalf of Bob should fail.
When login success, context data be saved .
Can use
GET https://openid.hydra:9002/oauth2/auth/sessions/consent?subject=foo@bar.com HTTP/1.1
check by subject.
This step is different quickstart.yml. Use https and t.tt domain. quickstart.yml start serve --dangerous-force-http
All become http. So last step can callback use http. This production way only use https. And token user only http. So use self OpenID client.
PS:
Here REST Client still return login page. go main server error log:
Post https://openid.hydra:9001/oauth2/token: x509: certificate signed by unknown authority
This is Go Server problem. See main.go Line:55-61 82-94 Fix this problem.
========== old ==========
3、Now have problem is token user. When you run *A, try to open web broswer. http://192.168.99.100:9010 then click "Authorize application" get error.
Because "Authorize application" still is 127.0.0.1. No way to change. So copy Link change it.
F... Now follow step run, Get level=error msg="An error occurred" debug="No CSRF value available in the session cookie" description="The request is not allowed" error=request_forbidden hint="You are not allowed to perform this action."
If you run same broswer and restart docker or clear cookie, do many way. Just try broswer private mode.
Try dex docker or binary failed, it's be pass.
Hydra docker-compose
1、get https://github.com/ory/hydra
docker-compose -f quickstart.yml -f quickstart-postgres.yml up --build
注意 quickstart.yml
run docker on host or run binary on host. hydra 5 minutes demo "IP Used" is 127.0.0.1
version: '3'
services:
hydra:
image: oryd/hydra:latest
ports:
- "4444:4444" # Public port
- "4445:4445" # Admin port
- "5555:5555" # Port for hydra token user
command:
serve all --dangerous-force-http
environment:
- URLS_SELF_ISSUER=http://127.0.0.1:4444
- URLS_CONSENT=http://127.0.0.1:3000/consent
- URLS_LOGIN=http://127.0.0.1:3000/login
- URLS_LOGOUT=http://127.0.0.1:3000/logout
- DSN=memory
- SECRETS_SYSTEM=youReallyNeedToChangeThis
- OIDC_SUBJECT_TYPES_SUPPORTED=public,pairwise
- OIDC_SUBJECT_TYPE_PAIRWISE_SALT=youReallyNeedToChangeThis
restart: unless-stopped
consent:
environment:
- HYDRA_ADMIN_URL=http://hydra:4445
image: oryd/hydra-login-consent-node:latest
ports:
- "3000:3000"
restart: unless-stopped
run VM or real server is real ip. Ex: 192.168.99.100 (docker-machine)
version: '3'
services:
hydra:
image: oryd/hydra:latest
ports:
- "4444:4444" # Public port
- "4445:4445" # Admin port
- "5555:5555" # Port for hydra token user
command:
serve all --dangerous-force-http
environment:
- URLS_SELF_ISSUER=http://192.168.99.100:4444
- URLS_CONSENT=http://192.168.99.100:3000/consent
- URLS_LOGIN=http://192.168.99.100:3000/login
- URLS_LOGOUT=http://192.168.99.100:3000/logout
- DSN=memory
- SECRETS_SYSTEM=youReallyNeedToChangeThis
- OIDC_SUBJECT_TYPES_SUPPORTED=public,pairwise
- OIDC_SUBJECT_TYPE_PAIRWISE_SALT=youReallyNeedToChangeThis
restart: unless-stopped
consent:
environment:
- HYDRA_ADMIN_URL=http://hydra:4445
image: oryd/hydra-login-consent-node:latest
ports:
- "3000:3000"
restart: unless-stopped
If have cors problems. see https://github.com/ory/hydra/blob/master/quickstart-cors.yml