Commit d7ce4996 authored by root's avatar root

finish

parent 7386f34c
## Redmine omniauth google
## Redmine omniauth myecp
This plugin is used to authenticate Redmine users using Google's OAuth2 provider.
This plugin is used to authenticate Redmine users using MyECP's OAuth2 provider.
### Installation:
......@@ -8,7 +8,7 @@ Download the plugin and install required gems:
```console
cd /path/to/redmine/plugins
git clone https://gitlab.my.ecp.fr/myecp/redmine-oauth.git redmine_omniauth_google
git clone https://gitlab.my.ecp.fr/myecp/redmine_omniauth_myecp.git
cd /path/to/redmine
bundle install
```
......@@ -20,39 +20,33 @@ touch /path/to/redmine/tmp/restart.txt
### Registration
To authenticate via Google you must first register your redmine instance via the Google Cloud Console
To authenticate via MyECP you must first register your redmine instance via the MyECP Clients Manager
* Go to the [registration](https://cloud.google.com/console) link.
* Click your Project's name
* Click "APIs & Auth"
* Click "Registered Apps"
* Click "Register App"
* Go to the [settings](https://my.ecp.fr/settings) link, and click on "Gérer mes clients", then on "Enregistrer un nouveau client".
* Type a name for the application, e.g. "My Redmine"
* Select "Web Application" as the Platform
* Click "Register"
* Click "OAuth 2.0 Client ID"
* Enter "https://mydomain.com/redmine/oauth2callback", where "mydomain.com/redmine" is the domain / path for your redmine instance. *** The plugin will not work without this setting ***
* Click "Generate"
* Save the Client ID and Client Secret for the configuration of the Redmine plugin (see below)
* Select Authorization Code
* Enter as a redirect URI "https://mydomain.com/redmine/oauth2callback", where "mydomain.com/redmine" is the domain / path for your redmine instance. *** The plugin will not work without this setting ***
* Click "Enregistrer"
* After client is granted (you will receive an email), go back to "Gérer mes clients", and save the Client ID and Client Secret for the configuration of the Redmine plugin (see below)
### Configuration
* Login as a user with administrative privileges.
* In top menu select "Administration".
* Click "Plugins"
* In plugins list, click "Configure" in the row for "Redmine Omniauth Google plugin"
* Enter the Сlient ID & Client Secret shown when you registered your application via Google Cloud Console.
* In plugins list, click "Configure" in the row for "Redmine Omniauth MyECP plugin"
* Enter the Сlient ID & Client Secret shown when you registered your application via MyECP Cloud Console.
* Check the box near "Oauth authentication"
* Click Apply.
Users can now to use their Google Account to log in to your instance of Redmine.
Users can now to use their MyECP Account to log in to your instance of Redmine.
Additionaly
* Setup value Autologin in Settings on tab Authentification
### Other options
By default, all user email domains are allowed to authenticate through Google.
By default, all user email domains are allowed to authenticate through MyECP.
If you want to limit the user email domains allowed to use the plugin, list one per line in the "Allowed domains" text box.
For example:
......@@ -62,15 +56,18 @@ onedomain.com
otherdomain.com
```
With the above configuration, only users with email addresses on the domains "onedomain.com" and "otherdomain.com" will be allowed to acccess your Redmine instance using Google OAuth.
With the above configuration, only users with email addresses on the domains "onedomain.com" and "otherdomain.com" will be allowed to acccess your Redmine instance using MyECP OAuth.
### Authentication Workflow
1. An unauthenticated user requests the URL to your Redmine instance.
2. User clicks the "Login via Google" buton.
3. The plugin redirects them to a Google sign in page if they are not already signed in to their Google account.
4. Google redirects user back to Redmine, where the Google OAuth plugin's controller takes over.
2. User clicks the "Login via MyECP" buton.
3. The plugin redirects them to a MyECP sign in page if they are not already signed in to their MyECP account.
4. MyECP redirects user back to Redmine, where the MyECP OAuth plugin's controller takes over.
One of the following cases will occur:
1. If self-registration is enabled (Under Administration > Settings > Authentication), user is redirected to 'my/page'
2. Otherwse, the an account is created for the user (referencing their Google OAuth2 ID). A Redmine administrator must activate the account for it to work.
2. Otherwse, the an account is created for the user (referencing their MyECP OAuth2 ID). A Redmine administrator must activate the account for it to work.
This plugin is completeley based on the work from [Twinslash](https://github.com/twinslash/redmine_omniauth_google)
......@@ -4,67 +4,72 @@ require 'json'
class RedmineOauthController < AccountController
include Helpers::MailHelper
include Helpers::Checker
def oauth_google
if Setting.plugin_redmine_omniauth_google[:oauth_authentification]
def oauth_myecp
if Setting.plugin_redmine_omniauth_myecp[:oauth_authentification]
session[:back_url] = params[:back_url]
redirect_to oauth_client.auth_code.authorize_url(:redirect_uri => oauth_google_callback_url, :scope => scopes)
redirect_to oauth_client.auth_code.authorize_url(:redirect_uri => oauth_myecp_callback_url, :scope => scopes, :state => 'okok')
else
password_authentication
end
end
def oauth_google_callback
def oauth_myecp_callback
if params[:error]
flash[:error] = l(:notice_access_denied)
redirect_to signin_path
else
token = oauth_client.auth_code.get_token(params[:code], :redirect_uri => oauth_google_callback_url)
result = token.get('https://dev.my.ecp.fr/testapi/who')
token = oauth_client.auth_code.get_token(params[:code], :redirect_uri => oauth_myecp_callback_url, :state => 'okok')
result = token.get('https://my.ecp.fr/m')
info = JSON.parse(result.body)
if info
if allowed_domain_for?(info["email"])
allowed_domain = allowed_domain_for?(info["mail"])
for mail in info["other_mails"]
allowed_domain ||= allowed_domain_for?(mail)
end
if allowed_domain
try_to_login info
else
flash[:error] = l(:notice_domain_not_allowed, :domain => parse_email(info["email"])[:domain])
redirect_to signin_path
end
else
flash[:error] = l(:notice_unable_to_obtain_google_credentials)
flash[:error] = l(:notice_unable_to_obtain_myecp_credentials)
redirect_to signin_path
end
end
end
def try_to_login info
params[:back_url] = session[:back_url]
session.delete(:back_url)
user = User.find_or_initialize_by_mail(info["email"])
params[:back_url] = session[:back_url]
session.delete(:back_url)
for mail in info["other_mails"]+[info["mail"]]
user = User.find_by_mail mail
break if user.is_a? User
end
user = User.initialize unless user.is_a? User
if user.new_record?
# Self-registration off
redirect_to(home_url) && return unless Setting.self_registration?
# Create on the fly
user.firstname, user.lastname = info["name"].split(' ') unless info['name'].nil?
user.firstname ||= info[:given_name]
user.lastname ||= info[:family_name]
user.mail = info["email"]
user.login = parse_email(info["email"])[:login]
user.login ||= [user.firstname, user.lastname]*"."
user.firstname = info['first_name']
user.lastname = info['last_name']
user.mail = info['mail']
user.login = info['login']
user.random_password
user.register
case Setting.self_registration
when '1'
register_by_email_activation(user) do
onthefly_creation_failed(user)
end
when '3'
register_automatically(user) do
onthefly_creation_failed(user)
end
else
register_manually_by_administrator(user) do
onthefly_creation_failed(user)
end
when '1'
register_by_email_activation(user) do
onthefly_creation_failed(user)
end
when '3'
register_automatically(user) do
onthefly_creation_failed(user)
end
else
register_manually_by_administrator(user) do
onthefly_creation_failed(user)
end
end
else
# Existing record
......@@ -84,13 +89,13 @@ class RedmineOauthController < AccountController
def oauth_client
@client ||= OAuth2::Client.new(settings[:client_id], settings[:client_secret],
:site => 'https://dev.my.ecp.fr',
:site => 'https://my.ecp.fr',
:authorize_url => '/oauth/v2/auth',
:token_url => '/oauth/v2/token')
end
def settings
@settings ||= Setting.plugin_redmine_omniauth_google
@settings ||= Setting.plugin_redmine_omniauth_myecp
end
def scopes
......
<%= stylesheet_link_tag 'buttons', :plugin => 'redmine_omniauth_google' %>
<%= stylesheet_link_tag 'buttons', :plugin => 'redmine_omniauth_myecp' %>
<% if Setting.plugin_redmine_omniauth_google[:oauth_authentification] %>
<%= link_to oauth_google_path(:back_url => back_url) do %>
<% if Setting.plugin_redmine_omniauth_myecp[:oauth_authentification] %>
<%= link_to oauth_myecp_path(:back_url => back_url) do %>
<%= button_tag :class => 'button-login' do %>
<%= image_tag('/plugin_assets/redmine_omniauth_google/images/google_login_icon.png', :class => 'button-login-icon', :alt => l(:login_via_google)) %>
<%= content_tag :div, l(:login_via_google), :class => 'button-login-text' %>
<%= content_tag :div, l(:login_via_myecp), :class => 'button-login-text' %>
<% end %>
<% end %>
<% end %>
en:
notice_unable_to_obtain_google_credentials: "Unable to obtain credentials from Google."
notice_unable_to_obtain_myecp_credentials: "Unable to obtain credentials from MyECP."
notice_domain_not_allowed: "You can not login using %{domain} domain."
notice_access_denied: "You must allow to use you Google credentials to enter this site."
login_via_google: "Login via Google"
notice_access_denied: "You must allow to use you MyECP credentials to enter this site."
login_via_myecp: "Login via MyECP"
ru:
notice_unable_to_obtain_google_credentials: "Не удалось получить данные от Google."
notice_domain_not_allowed: "Вы не можете войти в систему при помощи домена %{domain}."
notice_access_denied: "Для корректного входа необходимо разрешить приложению доступ к аккаунту."
login_via_google: "Войти с Google"
get 'oauth_google', :to => 'redmine_oauth#oauth_google'
get 'oauth2callback', :to => 'redmine_oauth#oauth_google_callback', :as => 'oauth_google_callback'
get 'oauth_myecp', :to => 'redmine_oauth#oauth_myecp'
get 'oauth2callback', :to => 'redmine_oauth#oauth_myecp_callback', :as => 'oauth_myecp_callback'
require 'redmine'
require_dependency 'redmine_omniauth_google/hooks'
require_dependency 'redmine_omniauth_myecp/hooks'
Redmine::Plugin.register :redmine_omniauth_google do
name 'Redmine Omniauth Google plugin'
author 'Dmitry Kovalenok'
description 'This is a plugin for Redmine registration through google'
Redmine::Plugin.register :redmine_omniauth_myecp do
name 'Redmine Omniauth MyECP plugin'
author 'Paul des Garets'
description 'This is a plugin for Redmine registration through MyECP, based on Omniauth google plugin.'
version '0.0.1'
url 'https://github.com/twinslash/redmine_omniauth_google'
url 'https://gitlab.my.ecp.fr/myecp/redmine_omniauth_myecp'
author_url 'http://twinslash.com'
settings :default => {
:client_id => "",
:client_secret => "",
:oauth_autentification => false,
:allowed_domains => ""
}, :partial => 'settings/google_settings'
:allowed_domains => "via.ecp.fr student.ecp.fr"
}, :partial => 'settings/myecp_settings'
end
module Helpers
module Checker
def allowed_domain_for? email
allowed_domains = Setting.plugin_redmine_omniauth_google[:allowed_domains]
allowed_domains = Setting.plugin_redmine_omniauth_myecp[:allowed_domains]
return unless allowed_domains
allowed_domains = allowed_domains.split
return true if allowed_domains.empty?
allowed_domains.index(parse_email(email)[:domain])
end
end
end
\ No newline at end of file
end
module RedmineOmniauthGoogle
module RedmineOmniauthMyECP
class Hooks < Redmine::Hook::ViewListener
def view_account_login_bottom(context = {})
context[:controller].send(:render_to_string, {
......
......@@ -30,58 +30,58 @@ class RedmineOauthControllerTest < ActionController::TestCase
OAuth2::Response.any_instance.stubs(:body => @default_response_body.merge(options).to_json)
end
def test_oauth_google_with_enabled_oauth_authentification
Setting.plugin_redmine_omniauth_google[:oauth_authentification] = nil
get :oauth_google
def test_oauth_myecp_with_enabled_oauth_authentification
Setting.plugin_redmine_omniauth_myecp[:oauth_authentification] = nil
get :oauth_myecp
assert_response 404
end
def test_oauth_google_callback_for_existing_non_active_user
def test_oauth_myecp_callback_for_existing_non_active_user
Setting.self_registration = '2'
user = new_user :status => User::STATUS_REGISTERED
assert user.save
set_response_body_stub
get :oauth_google_callback
get :oauth_myecp_callback
assert_redirected_to signin_path
end
def test_oauth_google_callback_for_existing_active_user
def test_oauth_myecp_callback_for_existing_active_user
user = new_user
user.activate
assert user.save
set_response_body_stub
get :oauth_google_callback
get :oauth_myecp_callback
assert_redirected_to :controller => 'my', :action => 'page'
end
def test_oauth_google_callback_for_new_user_with_valid_credentials_and_sefregistration_enabled
def test_oauth_myecp_callback_for_new_user_with_valid_credentials_and_sefregistration_enabled
Setting.self_registration = '3'
set_response_body_stub
get :oauth_google_callback
get :oauth_myecp_callback
assert_redirected_to :controller => 'my', :action => 'account'
user = User.find_by_mail(@default_response_body[:email])
assert_equal user.mail, @default_response_body[:email]
assert_equal user.login, parse_email(@default_response_body[:email])[:login]
end
def test_oauth_google_callback_for_new_user_with_valid_credentials_and_sefregistration_disabled
def test_oauth_myecp_callback_for_new_user_with_valid_credentials_and_sefregistration_disabled
Setting.self_registration = '2'
set_response_body_stub
get :oauth_google_callback
get :oauth_myecp_callback
assert_redirected_to signin_path
end
def test_oauth_google_callback_with_new_user_with_invalid_oauth_provider
def test_oauth_myecp_callback_with_new_user_with_invalid_oauth_provider
Setting.self_registration = '3'
set_response_body_stub :verified_email => false
get :oauth_google_callback
get :oauth_myecp_callback
assert_redirected_to signin_path
end
def test_oauth_google_callback_with_new_user_created_with_email_activation_should_have_a_token
def test_oauth_myecp_callback_with_new_user_created_with_email_activation_should_have_a_token
Setting.self_registration = '1'
set_response_body_stub
get :oauth_google_callback
get :oauth_myecp_callback
assert_redirected_to :signin
user = User.find_by_mail(@default_user_credentials[:mail])
assert user
......@@ -89,28 +89,28 @@ class RedmineOauthControllerTest < ActionController::TestCase
assert token
end
def test_oauth_google_callback_with_new_user_created_with_manual_activation
def test_oauth_myecp_callback_with_new_user_created_with_manual_activation
Setting.self_registration = '2'
set_response_body_stub
get :oauth_google_callback
get :oauth_myecp_callback
assert_redirected_to :signin
user = User.find_by_mail(@default_user_credentials[:mail])
assert user
assert_equal User::STATUS_REGISTERED, user.status
end
def test_oauth_google_callback_with_not_allowed_email_domain
Setting.plugin_redmine_omniauth_google[:allowed_domains] = "twinslash.com"
def test_oauth_myecp_callback_with_not_allowed_email_domain
Setting.plugin_redmine_omniauth_myecp[:allowed_domains] = "twinslash.com"
set_response_body_stub
get :oauth_google_callback
get :oauth_myecp_callback
assert_redirected_to :signin
end
def test_oauth_google_callback_with_allowed_email_domain
def test_oauth_myecp_callback_with_allowed_email_domain
Setting.self_registration = '3'
Setting.plugin_redmine_omniauth_google[:allowed_domains] = parse_email(@default_response_body[:email])[:domain]
Setting.plugin_redmine_omniauth_myecp[:allowed_domains] = parse_email(@default_response_body[:email])[:domain]
set_response_body_stub
get :oauth_google_callback
get :oauth_myecp_callback
assert_redirected_to :controller => 'my', :action => 'account'
end
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment