Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3pid authentication #60

Merged
merged 17 commits into from
Mar 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 119 additions & 2 deletions docs/features/authentication.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,39 @@
# Authentication
Authentication is an enchanced Identity feature of mxisd to ensure coherent and centralized identity management.

- [Description](#description)
- [Overview](#overview)
- [Getting started](#getting-started)
- [Synapse](#synapse)
- [mxisd](#mxisd)
- [Validate](#validate)
- [Next steps](#next-steps)
- [Profile auto-fil](#profile-auto-fill)
- [Advanced Authentication](#advanced-authentication)
- [Requirements](#requirements)
- [Configuration](#configuration)
- [Reverse Proxy](#reverse-proxy)
- [Apache2](#apache2)
- [DNS Overwrite](#dns-overwrite)
- [Backends](#backends)

## Description
Authentication is an enhanced Identity feature of mxisd to ensure coherent and centralized identity management.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Not necessary centralized - you can have several identity stores.
  • Identity management might be misleading, as mxisd doesn't do any management, only reads data.

I like the spirit of the sentence, but not the wording :D I also don't have a good idea about the wording at this point


It allows to use Identity stores configured in mxisd to authenticate users on your Homeserver.

This feature can also provide the ability to users to login on the Homeserver using their third party identities (3PIDs) provided by an Identity store.

## Overview
An overview of the Authentication process is depicted below:

```
Backends
Client +------+
| +-------------------------+ +--> | LDAP |
| +---------------+ /_matrix/identity | mxisd | | +------+
+-> | Reverse proxy | >------------------+ | | |
+--|------------+ | | | | +--------+
| +-----> Check wiht backends >------+--> | SQL DB |
| +-----> Check with backends >------+--> | SQL DB |
Login request | | | | +--------+
| | | | | |
| +--------------------------+ | +-----|-------------------+ +--> Others
Expand Down Expand Up @@ -52,3 +74,98 @@ Auto-filling user profile depends on two conditions:
- The REST auth module is configured for it, which is the case by default
- Your Identity store is configured to provide profile data. See your Identity store [documentation](../backends/) on
how to enable the feature.


## Advanced Authentication
The Authentication feature allows users to login to their Homeserver by using their 3PIDs registered in an available Identity store.

This is performed by intercepting the Homeserver endpoint `/_matrix/client/r0/login` as depicted below:

```
+----------------------------+
| Reverse Proxy |
| |
| | Step 1 +---------------------------+ Step 2
| | | |
Client+---->| /_matrix/client/r0/login +---------------->| | Look up address +---------+
| ^ | | mxisd - Identity server +----------------->| Backend |
| | | | | +---------+
| /_matrix/* +--+ +---------------------+ |
| | | +---------------+-----------+
| | | Step 4 |
| | | | Step 3
+---------------|------------+ |
| | /_matrix/client/r0/login
| +--------------+ |
| | | |
+---------------------->| Homeserver |<----+
| |
+--------------+

```

Steps of user authentication using a 3PID:
1. The intercepted login request is directly sent to mxisd instead of the Homeserver.
2. Enabled backends are queried for a matching user identity in order to modify the request to use the user name.
3. The Homeserver, from which the request was intercepted, is queried using the request at previous step. Its address is resolved using the DNS Overwrite feature to reach its internal address on a non-encrypted port.
4. The response from the Homeserver is sent back to the client, believing it was the HS which directly answered.

### Requirements
- Reverse proxy setup
- Homeserver
- Compatible Identity backends:
- LDAP
- SQL
- REST

### Configuration

#### Reverse Proxy

##### Apache2
The specific configuration to put under the relevant `VirtualHost`:
```
ProxyPass /_matrix/client/r0/login http://localhost:8090/_matrix/client/r0/login
```
`ProxyPreserveHost` or equivalent must be enabled to detect to which Homeserver mxisd should talk to when building results.

Your VirtualHost should now look like this:
```
<VirtualHost *:443>
ServerName example.org

...

ProxyPreserveHost on
ProxyPass /_matrix/client/r0/login http://localhost:8090/_matrix/client/r0/login
ProxyPass /_matrix/identity/ http://localhost:8090/_matrix/identity/
ProxyPass /_matrix/ http://localhost:8008/_matrix/
</VirtualHost>
```

#### DNS Overwrite
Just like you need to configure a reverse proxy to send client requests to mxisd, you also need to configure mxisd with the internal IP of the Homeserver so it can talk to it directly to integrate its directory search.


To do so, put the following configuration in your `application.yaml`:
```
dns.overwrite.homeserver.client:
- name: 'example.org'
value: 'http://localhost:8008'
```
`name` must be the hostname of the URL that clients use when connecting to the Homeserver.
In case the hostname is the same as your Matrix domain, you can use `${matrix.domain}` to auto-populate the `value` using the `matrix.domain` configuration option and avoid duplicating it.

value is the base internal URL of the Homeserver, without any /_matrix/.. or trailing /.

#### Backends
The Backends should be configured as described in the documentation of the [Directory User](directory-users.md) feature.









111 changes: 111 additions & 0 deletions src/main/java/io/kamax/mxisd/backend/memory/MemoryIdentityStore.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* mxisd - Matrix Identity Server Daemon
* Copyright (C) 2018 Maxime Dor
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package io.kamax.mxisd.backend.memory;

import io.kamax.matrix.MatrixID;
import io.kamax.matrix.ThreePid;
import io.kamax.matrix._MatrixID;
import io.kamax.mxisd.UserIdType;
import io.kamax.mxisd.auth.provider.AuthenticatorProvider;
import io.kamax.mxisd.auth.provider.BackendAuthResult;
import io.kamax.mxisd.config.MatrixConfig;
import io.kamax.mxisd.config.memory.MemoryIdentityConfig;
import io.kamax.mxisd.config.memory.MemoryStoreConfig;
import io.kamax.mxisd.config.memory.MemoryThreePid;
import io.kamax.mxisd.lookup.SingleLookupReply;
import io.kamax.mxisd.lookup.SingleLookupRequest;
import io.kamax.mxisd.lookup.ThreePidMapping;
import io.kamax.mxisd.lookup.provider.IThreePidProvider;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.List;
import java.util.Optional;

@Component
public class MemoryIdentityStore implements AuthenticatorProvider, IThreePidProvider {

private final Logger logger = LoggerFactory.getLogger(MemoryIdentityStore.class);

private final MatrixConfig mxCfg;
private final MemoryStoreConfig cfg;

@Autowired
public MemoryIdentityStore(MatrixConfig mxCfg, MemoryStoreConfig cfg) {
this.mxCfg = mxCfg;
this.cfg = cfg;
}

public Optional<MemoryIdentityConfig> findByUsername(String username) {
return cfg.getIdentities().stream().filter(id -> StringUtils.equals(id.getUsername(), username)).findFirst();
}

@Override
public boolean isEnabled() {
return cfg.isEnabled();
}

@Override
public boolean isLocal() {
return true;
}

@Override
public int getPriority() {
return Integer.MAX_VALUE;
}

@Override
public Optional<SingleLookupReply> find(SingleLookupRequest request) {
logger.info("Performing lookup {} of type {}", request.getThreePid(), request.getType());
ThreePid req = new ThreePid(request.getType(), request.getThreePid());
for (MemoryIdentityConfig id : cfg.getIdentities()) {
for (MemoryThreePid threepid : id.getThreepids()) {
if (req.equals(new ThreePid(threepid.getMedium(), threepid.getAddress()))) {
return Optional.of(new SingleLookupReply(request, new MatrixID(id.getUsername(), mxCfg.getDomain())));
}
}
}

return Optional.empty();
}

@Override
public List<ThreePidMapping> populate(List<ThreePidMapping> mappings) {
return Collections.emptyList();
}

@Override
public BackendAuthResult authenticate(_MatrixID mxid, String password) {
return findByUsername(mxid.getLocalPart()).map(id -> {
if (!StringUtils.equals(id.getUsername(), mxid.getLocalPart())) {
return BackendAuthResult.failure();
} else {
return BackendAuthResult.success(mxid.getId(), UserIdType.MatrixID, "");
}
}).orElseGet(BackendAuthResult::failure);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* mxisd - Matrix Identity Server Daemon
* Copyright (C) 2018 Maxime Dor
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package io.kamax.mxisd.config.memory;

import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component
public class MemoryIdentityConfig {

private String username;
private String password;
private List<MemoryThreePid> threepids = new ArrayList<>();

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public List<MemoryThreePid> getThreepids() {
return threepids;
}

public void setThreepids(List<MemoryThreePid> threepids) {
this.threepids = threepids;
}

}
51 changes: 51 additions & 0 deletions src/main/java/io/kamax/mxisd/config/memory/MemoryStoreConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* mxisd - Matrix Identity Server Daemon
* Copyright (C) 2018 Maxime Dor
*
* https://www.kamax.io/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package io.kamax.mxisd.config.memory;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

import java.util.List;

@Configuration
@ConfigurationProperties("memory")
public class MemoryStoreConfig {

private boolean enabled;
private List<MemoryIdentityConfig> identities;

public boolean isEnabled() {
return enabled;
}

public void setEnabled(boolean enabled) {
this.enabled = enabled;
}

public List<MemoryIdentityConfig> getIdentities() {
return identities;
}

public void setIdentities(List<MemoryIdentityConfig> identities) {
this.identities = identities;
}

}
Loading