-
Notifications
You must be signed in to change notification settings - Fork 10
Client-Side (Mutual) Authentication #59
Comments
You could look are there related settings at: Wekan LDAP code is at: Wekan can be run behind Apache: Do you know about this? |
Thanks for the reply. I'm familiar with the links. I have a successful docker deployment with LDAP configured and running. Works great. But I want to take it a step further. Let's say I follow the third link above and setup a reverse proxy. I would add directives to fetch client certificates (if they have any): # activate the client certificate authentication I would then create a session variable that forwards the certificate data to Wekan: My question now is how does wekan use SSL_CLIENT_S_DN to login (or create) the user? In other words, can Wekan automatically log-in users that have already been authenticated by the reverse proxy? As a comparison, when I setup a MediaWiki server, I loaded the Extension:Auth remoteuser extension to add this functionality. I'm curious if this capability is available in Wekan? |
I presume it's not yet in Wekan, and would require adding code for checking that header at layouts.* at https://github.com/wekan/wekan/tree/devel/client/components/main login page and/or wekan/server/authentication.js and then based on that check it similarly with Javascript code and login user, with similar code like in that PHP extension. Anyway, that extension PHP code is not long, and everything required to login is already in Wekan LDAP code, so this would require just someone that has time to look at the code, figure it out and add PR. |
Hi! Do you have an update on this feature request ? I'm also interrested, same use case as @perlhub. |
Not yet. Do you have time to help? |
Not for contributing to the code, but anything that can help you (test version, paste logs, ...). |
I gave a look at the code to see if I could develop it rapidly, but it seems to be impossible to read custom HTTP Headers from the Meteor server side. I'm not very familiar with Meteor, and I looked the entire web for a few hours without solution. The problem is that Meteor filters HTTP Header based on a whitelist, and it's very obscure to me, and not documented. Aside from this, I think I know how to implement it. |
How would you implement this? Is there existing serverside implementation in some other programming language? For example Javascript or PHP? I'm currently researching how to make non-Meteor version of Wekan. |
Doh, now I noticed above the link to MediaWiki example code. I'll look at it. |
Is this Kanboard feature also about this Client-Side (Mutual) Authentication issue? Both Wekan and Kanboard have MIT license. There is differences in web UI and other features. |
How would I implement itSo as I said I'm new to Meteor and maybe it's not the best way to do it, but I tested it with hard coded values and it works as expected. In header-login.js, I created a new Authentication Handler : Accounts.registerLoginHandler("headers", function(loginRequest) {
if (!loginRequest.checkHeaders) {
return undefined;
}
console.log("Handling login from headers");
console.log(loginRequest);
// HERE IS THE PROBLEM : we need to find a way to get the request headers to get values of loginId, loginEmail, loginFirstname and loginLastname.
var sessionData = this.connection || (this._session ? this._session.sessionData : this._sessionData);
// only a few headers are visible because of the whitelist filtering
console.log(this);
console.log(sessionData);
// so i used fixed values for testing
var loginId = "user";
var loginEmail = "user@domain.com";
var loginFirstname = "User";
var loginLastname = "User";
const serviceName = 'headers';
const serviceData = {};
const serviceOptions = {
profile: {}
};
serviceData.id = loginId; // unique
const result = Accounts.updateOrCreateUserFromExternalService(
serviceName,
serviceData,
serviceOptions
);
if (!result || !result.userId) {
throw new Meteor.Error('someError', 'Some message');
}
// update username if you have one
Accounts.setUsername(result.userId, loginId);
// add email (not verified)
Accounts.addEmail(result.userId, loginEmail);
var stampedToken = Accounts._generateStampedLoginToken();
var hashStampedToken = Accounts._hashStampedToken(stampedToken);
const user = Users.findOne({username: loginId});
if (user) {
console.log("Found user !!");
Meteor.users.update(user._id, {
$push: {
'services.resume.loginTokens': hashStampedToken
}
});
console.log("Everything OK !!");
return {
userId: user._id,
token: stampedToken.token
};
}
console.log("No user");
return undefined;
}); And then in layout.js I added this (didnt know where to insert it, so I put it inside Template.userFormsLayout.onCreated and it seems OK. Accounts.callLoginMethod({
methodArguments: [{checkHeaders: true}],
userCallback(error, result) {
console.log("callLoginMethod returned!")
if (error) {
console.error(error);
}
else {
console.log("User logged");
FlowRouter.go('/')
}
},
});
}); |
Yes exactly ! |
Did you find yet where header whitelist is? I'm not sure could it be related to browser-policy? This is how Wekan serverside sets some CORS headers: There is also not yet merged PR for adding more CORS headers: For header login another issue: This maybe is how in plain javascript headers are read: Does any of this give you ideas how to get it working? |
In that header login issue, here are how I planned to do it, that's the explanation of that non-working code: |
No, I checked official online documentation/forums and some Stackoverflow posts but none said where it is located and how (if possible) to configure it. I found some piece of info here : https://www.phusionpassenger.com/library/indepth/meteor/secure_http_headers.html Meteor uses sockjs behind the scenes to transform requests into connection objects, and sockjs enforces a whitelist on headers, so using connection.httpHeaders won't work to access our secure headers from meteor.
No idea, I need to research more :(
I tried some solution base on
I'm aware of the other issue (#2019), actually I first landed on this issue when I started to dig it. For me this is a duplicate of this current issue we're discuting. I was planning to use the constants you already added in the code to get the correct headers.
I will look into it to see if I can be inspired :) |
Whoa, it was possible to read HTTP Headers without limitation? Then of course try to use it, to get it working. I did not even get that far that you did here. |
@xet7 I'll try to continue tomorrow (it's evening here in France) and I keep you updated. |
Thanks! That issue wekan/wekan#2019 has links to all commits I added when I tried to implement it. |
How it worksFrom https://www.phusionpassenger.com/library/indepth/meteor/secure_http_headers.html
Comments by xet7This above description is so clear and simple about how this works. It's not a problem that we use code to read all raw headers directly. In front of Wekan is the webserver (Caddy/Nginx/Apache/Siteminder/etc) that will drop extra headers that are coming from client, preventing header spoofing. Then that webserver (Caddy/Nginx/Apache/Siteminder/etc) adds it's own allowed headers. Then in Wekan is defined what header names to read, and autologins to Wekan. |
Sorry I wasn't able to make it work.. With A possible implementation would be to store the headers value from WebApp.rawConnectHandlers when it is accessible, and use them later. I tried to access some sort of Session storage, server side but private to the client making the request. But I didn't find anything working when the user is not yet logged... |
Thanks for looking into this guys. It sounds like you were able to fetch the HTTP headers, but not auto-login with them. I logged in to post another example link I found: https://grafana.com/docs/auth/auth-proxy/. It shows how Grafana does what we're trying to do. Behind my Apache reverse proxy I have Grafana and Wekan running. Apache logs me in, then forwards a custom header (i.e. X-WEBAUTH-USER) to Grafana and Wekan. Grafana then logs me in with the header username. It would be great if Wekan did this too. |
So does Grafana require only username in header to login? Is username same as e-mail address? Does it not use firstname and lastname at all? |
I think for Wekan, only required header would probably be username (like nickname or email address). Having firstname, lastname, fullname, gravatar URL etc would be optional. |
@xet7 Yea, only the username is required. But you can add additional headers. This is in their config file: # Optionally define more headers to sync other user attributes |
Is there support for client-side authentication? For example, to authenticate the user you request a client's certificate. Accounts would be created if the certs are trusted (based on a configured trust store).
For additional security, Wekan can connect to LDAP, find the user based on cert info and reject access unless they are in a configured group. You never need to request a password from the user.
I have LDAP setup, but I would love to fetch their client certificate instead of asking them to provide their account credentials. This is how I've setup access 8000 in the past with Apache for other webapps.
The text was updated successfully, but these errors were encountered: