Skip to content
Open
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
67 changes: 54 additions & 13 deletions SampleAuth.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ function register() {
$this->description = plugin_lang_get( 'description' );
$this->page = '';

$this->version = '0.1';
$this->version = '0.2';
$this->requires = array(
'MantisCore' => '2.3.0-dev',
'MantisCore' => '2.14.0-dev',
);

$this->author = 'MantisBT Team';
Expand All @@ -37,16 +37,23 @@ function hooks() {
return $t_hooks;
}

function config() {
return array(
# set to 'true', if the plugin can do autoprovisioning - otherwise only "known" users will be able to log in
'autoprovision' => true,
# sets the access level configured by autoprov; defaults to system configures default access level
'default_access_level' => config_get( 'default_new_account_access_level' )
);
}

function auth_user_flags( $p_event_name, $p_args ) {
# Don't access DB if db_is_connected() is false.

$t_username = $p_args['username'];

$t_user_id = $p_args['user_id'];

# If user is unknown, don't handle authentication for it, since this plugin doesn't do
# auto-provisioning
if( !$t_user_id ) {
# If user is unknown and autoprovision is not set, than don't handle authentication for it
if( !$t_user_id && ! plugin_config_get( 'autoprovision' ) ) {
return null;
}

Expand All @@ -55,14 +62,29 @@ function auth_user_flags( $p_event_name, $p_args ) {
return null;
}

$t_access_level = user_get_access_level( $t_user_id, ALL_PROJECTS );
if( $t_user_id ) {
Copy link
Member

Choose a reason for hiding this comment

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

Should the above user_is_anonymous() be inside this if statement?

Copy link
Author

Choose a reason for hiding this comment

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

I don't think so, and I really don't see any point getting the user_access_level if it's not really needed.

$t_access_level = user_get_access_level( $t_user_id, ALL_PROJECTS );

# Have administrators use default login flow
if( $t_access_level >= ADMINISTRATOR ) {
# Have administrators use default login flow
Copy link
Member

Choose a reason for hiding this comment

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

Use tabs instead of spaces across the PR.

Copy link
Author

Choose a reason for hiding this comment

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

I'm having tabs here in midnight commander, however, they are 4 spaces wide tabs.

if( $t_access_level >= ADMINISTRATOR ) {
return null;
}
}

# for everybody else use the custom authentication
/*
*
* add any filter parameters here
*
* e.g. if you want the plugin to handle usernames only which contain '@':
*
* if ( ! preg_match('/^.*@.*$/',$t_username) ) {
* return null;
* }
*
* or to use this custom authenticateion for everybody else:
*
*/

$t_flags = new AuthFlags();

# Passwords managed externally for all users
Expand All @@ -71,9 +93,28 @@ function auth_user_flags( $p_event_name, $p_args ) {

# No one can use standard auth mechanism

# Override Login page and Logout Redirect
$t_flags->setCredentialsPage( helper_url_combine( plugin_page( 'login', /* redirect */ true ), 'username=' . $t_username ) );
$t_flags->setLogoutRedirectPage( plugin_page( 'logout', /* redirect */ true ) );
# Override Credentials, Authenticator page and Logout Redirect - see 'pages' subdirectory
/*
*
* custom Credentials Page for user. This is displayed after the user did input his username (and the username is known to Mantis or plugin is autoprov capable)
*
*/
//$t_flags->setCredentialsPage( helper_url_combine( plugin_page( 'credentials', /* redirect */ true ), 'username=' . $t_username ) );
/*
*
* custom Authenticator Page for user. This is called, when the user entered both username and password in the standard MantisBT login flow
* username and password in $_POST
*
* Please NOTE: if you don't do any filtering - e.g. e-mail - than this will be the only Auth Plugin besides the built-in! Stacking is not (yet) supported
*
*/
$t_flags->setAuthenticatorPage( helper_url_combine( plugin_page( 'login', /* redirect */ true ), ( !empty($t_username) ? 'username=' . urlencode($t_username) : '' ) ) );
/*
*
* custom Logout Page for user.
*
*/
//$t_flags->setLogoutRedirectPage( plugin_page( 'logout', /* redirect */ true ) );

# No long term session for identity provider to be able to kick users out.
$t_flags->setPermSessionEnabled( false );
Expand Down
183 changes: 183 additions & 0 deletions core/CustomAuthPlugin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
<?php
/**
* MantisBT - A PHP based bugtracking system
*
* MantisBT is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* MantisBT 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MantisBT. If not, see <http://www.gnu.org/licenses/>.
*
* @copyright Copyright 2002 MantisBT Team - mantisbt-dev@lists.sourceforge.net
*/

/**
* Class for dealing with custom authentication requests
*
*
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*
* Class is written for demonstration purposes ONLY!!!
*
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*
* @copyright Tamas Dajka 2018
* @author Tamas Dajka <viper@vipernet.hu>
* @link http://www.mantisbt.org
* @package MantisBT
* @subpackage classes
* @plugin SampleAuth
*/

/*
*
* User API is needed for user auto provision
*
*/
require_api( 'user_api.php' );
require_api( 'email_api.php' );

class CustomAuthPlugin {

/**
* Constructor
*/
function __construct() {
# spaceholder
}

/**
* login
*
* @params: username, password
* @return:
* - false on login failure
* - username on login success
*/
function login( $username, $password ) {
/*
*
* Check access/auth in remote system
*
*/
if ( !$this->auth($username,$password) ) {
return false;
}

/*
*
* Should we autoprovision the user?
*
*/
if( plugin_config_get( 'autoprovision' ) ) {
/*
* Check if user exists, probably needs customization
*/
if( ! user_get_id_by_name($username) ) {
/*
* data needed for autorpovision:
* - username
* - password
*
* Optional params:
*
* - email
* - access_level (null)
* - protected (false)
* - enabled (true)
* - realname
* - admin_name
*
*/

$t_user_data = $this->get_user_data( $username );

/*
* create user, but with empty e-mail => prevent mantis from sending signup e-mail
* we set a strong random password
*
* To get this work, you either have to set $g_allow_blank_email = ON, or change the value here on-the-fly (don't forget to set it back)
*
*/
$original_g_allow_blank_email = config_get( 'allow_blank_email' );
config_set_global( 'allow_blank_email', ON );
user_create( $username, auth_generate_random_password(24), '', $t_user_data['access_level'], false, true, $t_user_data['realname'] );
config_set_global( 'allow_blank_email', $original_g_allow_blank_email );

/*
* Set user e-mail
*/
if( !is_blank( $t_user_data['email'] ) && email_is_valid( $t_user_data['email'] ) && ( $t_user_id = user_get_id_by_name( $username ) ) ) {
user_set_field( $t_user_id,'email', $t_user_data['email'] );
}
}
}

return $username;
}

/**
* logout
*
* @return: bool
*/
function logout() {
# spaceholder
return true;
}

/**
* collects user data from auth system
*
* @return: array()
*/
function get_user_data( $username = '' ) {
if ( empty($username) ) {
return array();
}

/*
* dummy data for now, access_level 25 is REPORTER -> see <ROOT>/core/constant_inc.php
*/
return array( 'username' => $username, 'email' => 'john.doe@gmail.com', 'access_level' => config_get( 'default_new_account_access_level' ), 'realname' => 'John Doe' );
}

/**
* Auth validity check
*
* @params: username, password
* @return: bool
*/
function auth( $username, $password ) {
if ( empty( $username ) || empty( $password ) ) {
return false;
}

/*
* We should check for external auth here
*
* dummy return for now
*/

# comment this out for testing or write your own
return false;

/* example authentication */
if( $username == 'john.doe' && $password == 'Abc.123' ) {
Copy link
Member

Choose a reason for hiding this comment

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

just return the expression instead if/else blocks.

Copy link
Author

Choose a reason for hiding this comment

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

Sorry, I don't get what you mean here. The 'auth' function should do the authentication, the john.doe is just an example for a simple behaviour.

return true;
} else {
return false;
}
}
}
56 changes: 56 additions & 0 deletions pages/credentials.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php
# Copyright (c) MantisBT Team - mantisbt-dev@lists.sourceforge.net
# Licensed under the MIT license

require_once( 'core.php' );
require_api( 'authentication_api.php' );
require_api( 'user_api.php' );

$f_username = gpc_get( 'username' );
$f_reauthenticate = gpc_get_bool( 'reauthenticate', false );
$f_return = gpc_get_string( 'return', config_get( 'default_home_page' ) );

$t_return = string_url( string_sanitize_url( $f_return ) );

/*
*
* Set up and call the external authenticator with the username provided
* (password is not known this time - makeing use of SSO possible
*
*/

$t_user_id = is_blank( $f_username ) ? false : user_get_id_by_name( $f_username );

if( $t_user_id == false ) {
$t_query_args = array(
'error' => 1,
'username' => $f_username,
);

if( !is_blank( 'return' ) ) {
$t_query_args['return'] = $t_return;
}

if( $f_reauthenticate ) {
$t_query_args['reauthenticate'] = 1;
}

$t_query_text = http_build_query( $t_query_args, '', '&' );
// we will create a loop this way - this will redirect us again to this login page...
//$t_uri = auth_login_page( $t_query_text );
// no "stack like" auth mechs, forcing default page on error
$t_uri = helper_url_combine( AUTH_PAGE_USERNAME, $t_query_args);

print_header_redirect( $t_uri );
}

# Let user into MantisBT
auth_login_user( $t_user_id );

# Redirect to original page user wanted to access before authentication
if( !is_blank( $t_return ) ) {
print_header_redirect( 'login_cookie_test.php?return=' . $t_return );
}

# If no return page, redirect to default page
print_header_redirect( config_get( 'default_home_page' ) );
33 changes: 29 additions & 4 deletions pages/login.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,36 @@
require_api( 'authentication_api.php' );
require_api( 'user_api.php' );

$f_username = gpc_get( 'username' );
$f_username = gpc_get_string( 'username', '' );
$f_password = gpc_get_string( 'password', '' );
$f_reauthenticate = gpc_get_bool( 'reauthenticate', false );
$f_return = gpc_get_string( 'return', config_get( 'default_home_page' ) );

$t_return = string_url( string_sanitize_url( $f_return ) );

# TODO: use custom authentication method here.
$f_username = auth_prepare_username( $f_username );
$f_password = auth_prepare_password( $f_password );

/*
*
* Log in the user with the custom class
*
* class should return username/false upon successful/failed login
*
*/

plugin_require_api( 'core/CustomAuthPlugin.php' );
$cap = new CustomAuthPlugin();
if ( ( $f_username = $cap->login($f_username,$f_password) ) ) {
/*
*
* All set, good to go
*
* if you want to assign the user to project(s) based on a criteria
* than this is the right place. Don't forget to check if it's already assigned
*
*/
}

$t_user_id = is_blank( $f_username ) ? false : user_get_id_by_name( $f_username );

Expand All @@ -31,8 +54,10 @@
}

$t_query_text = http_build_query( $t_query_args, '', '&' );

$t_uri = auth_login_page( $t_query_text );
// we will create a loop this way - this will redirect us again to this login page...
//$t_uri = auth_login_page( $t_query_text );
// no "stack like" auth mechs, forcing default page on error
$t_uri = helper_url_combine( AUTH_PAGE_USERNAME, $t_query_args);

print_header_redirect( $t_uri );
}
Expand Down
Loading