Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Wolfgang Knopki
simplesamlphp_sqlauthbcrypt
Commits
5f8d03fe
Commit
5f8d03fe
authored
Nov 12, 2020
by
Wolfgang Knopki
Browse files
added compatibility with simplesamlphp 1.19
parent
8e8e5b35
Changes
1
Hide whitespace changes
Inline
Side-by-side
lib/Auth/Source/SQL.php
View file @
5f8d03fe
...
...
@@ -12,216 +12,222 @@
* @package simpleSAMLphp
* @version $Id$
*/
class
sspmod_sqlauthBcrypt_Auth_Source_SQL
extends
sspmod_core_Auth_UserPassBase
{
/**
* The DSN we should connect to.
*/
private
$dsn
;
/**
* The username we should connect to the database with.
*/
private
$username
;
/**
* The password we should connect to the database with.
*/
private
$password
;
/**
* The query we should use to retrieve the attributes for the user.
*
* The username and password will be available as :username and :password.
*/
private
$query
;
/**
* The pepper used to generate the password hash.
*/
private
$pepper
;
/**
* The column holding the password hash.
*/
private
$hash_column
;
/**
* Constructor for this authentication source.
*
* @param array $info Information about this authentication source.
* @param array $config Configuration.
*/
public
function
__construct
(
$info
,
$config
)
{
assert
(
'is_array($info)'
);
assert
(
'is_array($config)'
);
/* Call the parent constructor first, as required by the interface. */
parent
::
__construct
(
$info
,
$config
);
/* Make sure that all required parameters are present. */
foreach
(
array
(
'dsn'
,
'username'
,
'password'
,
'query'
,
'pepper'
)
as
$param
)
{
if
(
!
array_key_exists
(
$param
,
$config
))
{
throw
new
Exception
(
'Missing required attribute \''
.
$param
.
'\' for authentication source '
.
$this
->
authId
);
}
if
(
!
is_string
(
$config
[
$param
]))
{
throw
new
Exception
(
'Expected parameter \''
.
$param
.
'\' for authentication source '
.
$this
->
authId
.
' to be a string. Instead it was: '
.
var_export
(
$config
[
$param
],
TRUE
));
}
}
$this
->
dsn
=
$config
[
'dsn'
];
$this
->
username
=
$config
[
'username'
];
$this
->
password
=
$config
[
'password'
];
$this
->
query
=
$config
[
'query'
];
$this
->
pepper
=
$config
[
'pepper'
];
$this
->
hash_column
=
$config
[
'hash_column'
];
}
/**
* Create a database connection.
*
* @return PDO The database connection.
*/
private
function
connect
()
{
try
{
$db
=
new
PDO
(
$this
->
dsn
,
$this
->
username
,
$this
->
password
);
}
catch
(
PDOException
$e
)
{
throw
new
Exception
(
'sqlauthBcrypt:'
.
$this
->
authId
.
': - Failed to connect to \''
.
$this
->
dsn
.
'\': '
.
$e
->
getMessage
());
}
$db
->
setAttribute
(
PDO
::
ATTR_ERRMODE
,
PDO
::
ERRMODE_EXCEPTION
);
$driver
=
explode
(
':'
,
$this
->
dsn
,
2
);
$driver
=
strtolower
(
$driver
[
0
]);
/* Driver specific initialization. */
switch
(
$driver
)
{
case
'mysql'
:
/* Use UTF-8. */
$db
->
exec
(
"SET NAMES 'utf8'"
);
break
;
case
'pgsql'
:
/* Use UTF-8. */
$db
->
exec
(
"SET NAMES 'UTF8'"
);
break
;
}
return
$db
;
}
/**
* Attempt to log in using the given username and password.
*
* On a successful login, this function should return the users attributes. On failure,
* it should throw an exception. If the error was caused by the user entering the wrong
* username or password, a SimpleSAML_Error_Error('WRONGUSERPASS') should be thrown.
*
* Note that both the username and the password are UTF-8 encoded.
*
* @param string $username The username the user wrote.
* @param string $password The password the user wrote.
* @return array Associative array with the users attributes.
*/
protected
function
login
(
$username
,
$password
)
{
assert
(
'is_string($username)'
);
assert
(
'is_string($password)'
);
$db
=
$this
->
connect
();
try
{
$sth
=
$db
->
prepare
(
$this
->
query
);
}
catch
(
PDOException
$e
)
{
throw
new
Exception
(
'sqlauthBcrypt:'
.
$this
->
authId
.
': - Failed to prepare query: '
.
$e
->
getMessage
());
}
try
{
$res
=
$sth
->
execute
(
array
(
'username'
=>
$username
));
}
catch
(
PDOException
$e
)
{
throw
new
Exception
(
'sqlauthBcrypt:'
.
$this
->
authId
.
': - Failed to execute query: '
.
$e
->
getMessage
());
}
try
{
$data
=
$sth
->
fetchAll
(
PDO
::
FETCH_ASSOC
);
}
catch
(
PDOException
$e
)
{
throw
new
Exception
(
'sqlauth:'
.
$this
->
authId
.
': - Failed to fetch result set: '
.
$e
->
getMessage
());
}
SimpleSAML_Logger
::
info
(
'sqlauthBcrypt:'
.
$this
->
authId
.
': Got '
.
count
(
$data
)
.
' rows from database'
);
if
(
count
(
$data
)
===
0
)
{
/* No rows returned - invalid username */
SimpleSAML_Logger
::
error
(
'sqlauthBcrypt:'
.
$this
->
authId
.
': No rows in result set. Wrong username or sqlauthBcrypt is misconfigured.'
);
throw
new
SimpleSAML_Error_Error
(
'WRONGUSERPASS'
);
}
/* Validate stored password hash (must be in first row of resultset) */
$password_hash
=
$data
[
0
][
$this
->
hash_column
];
if
(
$password_hash
!==
crypt
(
$password
.
$this
->
pepper
,
$password_hash
))
{
/* Invalid password */
SimpleSAML_Logger
::
error
(
'sqlauthBcrypt:'
.
$this
->
authId
.
': Hash does not match. Wrong password or sqlauthBcrypt is misconfigured.'
);
throw
new
SimpleSAML_Error_Error
(
'WRONGUSERPASS'
);
}
/* Extract attributes. We allow the resultset to consist of multiple rows. Attributes
* which are present in more than one row will become multivalued. NULL values and
* duplicate values will be skipped. All values will be converted to strings.
*/
$attributes
=
array
();
foreach
(
$data
as
$row
)
{
foreach
(
$row
as
$name
=>
$value
)
{
if
(
$value
===
NULL
)
{
continue
;
}
if
(
$name
===
$this
->
hash_column
)
{
/* Don't add password hash to attributes */
continue
;
}
$value
=
(
string
)
$value
;
if
(
!
array_key_exists
(
$name
,
$attributes
))
{
$attributes
[
$name
]
=
array
();
}
if
(
in_array
(
$value
,
$attributes
[
$name
],
TRUE
))
{
/* Value already exists in attribute. */
continue
;
}
$attributes
[
$name
][]
=
$value
;
}
}
SimpleSAML_Logger
::
info
(
'sqlauthBcrypt:'
.
$this
->
authId
.
': Attributes: '
.
implode
(
','
,
array_keys
(
$attributes
)));
return
$attributes
;
}
/*class sspmod_sqlauthBcrypt_Auth_Source_SQL extends sspmod_core_Auth_UserPassBase {*/
namespace
SimpleSAML\Module\sqlauthbcrypt\Auth\Source
;
class
sql
extends
\
SimpleSAML\Module\core\Auth\UserPassBase
{
/**
* The DSN we should connect to.
*/
private
$dsn
;
/**
* The username we should connect to the database with.
*/
private
$username
;
/**
* The password we should connect to the database with.
*/
private
$password
;
/**
* The query we should use to retrieve the attributes for the user.
*
* The username and password will be available as :username and :password.
*/
private
$query
;
/**
* The pepper used to generate the password hash.
*/
private
$pepper
;
/**
* The column holding the password hash.
*/
private
$hash_column
;
/**
* Constructor for this authentication source.
*
* @param array $info Information about this authentication source.
* @param array $config Configuration.
*/
public
function
__construct
(
$info
,
$config
)
{
assert
(
'is_array($info)'
);
assert
(
'is_array($config)'
);
/* Call the parent constructor first, as required by the interface. */
parent
::
__construct
(
$info
,
$config
);
/* Make sure that all required parameters are present. */
foreach
(
array
(
'dsn'
,
'username'
,
'password'
,
'query'
,
'pepper'
)
as
$param
)
{
if
(
!
array_key_exists
(
$param
,
$config
))
{
throw
new
\
Exception
(
'Missing required attribute \''
.
$param
.
'\' for authentication source '
.
$this
->
authId
);
}
if
(
!
is_string
(
$config
[
$param
]))
{
throw
new
\
Exception
(
'Expected parameter \''
.
$param
.
'\' for authentication source '
.
$this
->
authId
.
' to be a string. Instead it was: '
.
var_export
(
$config
[
$param
],
TRUE
));
}
}
$this
->
dsn
=
$config
[
'dsn'
];
$this
->
username
=
$config
[
'username'
];
$this
->
password
=
$config
[
'password'
];
$this
->
query
=
$config
[
'query'
];
$this
->
pepper
=
$config
[
'pepper'
];
$this
->
hash_column
=
$config
[
'hash_column'
];
}
/**
* Create a database connection.
*
* @return PDO The database connection.
*/
private
function
connect
()
{
try
{
$db
=
new
\
PDO
(
$this
->
dsn
,
$this
->
username
,
$this
->
password
);
}
catch
(
\
PDOException
$e
)
{
throw
new
\
Exception
(
'sqlauthBcrypt:'
.
$this
->
authId
.
': - Failed to connect to \''
.
$this
->
dsn
.
'\': '
.
$e
->
getMessage
());
}
$db
->
setAttribute
(
\
PDO
::
ATTR_ERRMODE
,
\
PDO
::
ERRMODE_EXCEPTION
);
$driver
=
explode
(
':'
,
$this
->
dsn
,
2
);
$driver
=
strtolower
(
$driver
[
0
]);
/* Driver specific initialization. */
switch
(
$driver
)
{
case
'mysql'
:
/* Use UTF-8. */
$db
->
exec
(
"SET NAMES 'utf8'"
);
break
;
case
'pgsql'
:
/* Use UTF-8. */
$db
->
exec
(
"SET NAMES 'UTF8'"
);
break
;
}
return
$db
;
}
/**
* Attempt to log in using the given username and password.
*
* On a successful login, this function should return the users attributes. On failure,
* it should throw an exception. If the error was caused by the user entering the wrong
* username or password, a SimpleSAML_Error_Error('WRONGUSERPASS') should be thrown.
*
* Note that both the username and the password are UTF-8 encoded.
*
* @param string $username The username the user wrote.
* @param string $password The password the user wrote.
* @return array Associative array with the users attributes.
*/
protected
function
login
(
string
$username
,
string
$password
):
array
{
assert
(
'is_string($username)'
);
assert
(
'is_string($password)'
);
$db
=
$this
->
connect
();
try
{
$sth
=
$db
->
prepare
(
$this
->
query
);
}
catch
(
\
PDOException
$e
)
{
throw
new
\
Exception
(
'sqlauthBcrypt:'
.
$this
->
authId
.
': - Failed to prepare query: '
.
$e
->
getMessage
());
}
try
{
$res
=
$sth
->
execute
(
array
(
'username'
=>
$username
));
}
catch
(
\
PDOException
$e
)
{
throw
new
\
Exception
(
'sqlauthBcrypt:'
.
$this
->
authId
.
': - Failed to execute query: '
.
$e
->
getMessage
());
}
try
{
$data
=
$sth
->
fetchAll
(
\
PDO
::
FETCH_ASSOC
);
}
catch
(
\
PDOException
$e
)
{
throw
new
\
Exception
(
'sqlauth:'
.
$this
->
authId
.
': - Failed to fetch result set: '
.
$e
->
getMessage
());
}
\
SimpleSAML\Logger
::
info
(
'sqlauthBcrypt:'
.
$this
->
authId
.
': Got '
.
count
(
$data
)
.
' rows from database'
);
if
(
count
(
$data
)
===
0
)
{
/* No rows returned - invalid username */
\
SimpleSAML\Logger
::
error
(
'sqlauthBcrypt:'
.
$this
->
authId
.
': No rows in result set. Wrong username or sqlauthBcrypt is misconfigured.'
);
throw
new
\
SimpleSAML\Error\Error
(
'WRONGUSERPASS'
);
}
/* Validate stored password hash (must be in first row of resultset) */
$password_hash
=
$data
[
0
][
$this
->
hash_column
];
if
(
$password_hash
!==
crypt
(
$password
.
$this
->
pepper
,
$password_hash
))
{
/* Invalid password */
\
SimpleSAML\Logger
::
error
(
'sqlauthBcrypt:'
.
$this
->
authId
.
': Hash does not match. Wrong password or sqlauthBcrypt is misconfigured.'
);
throw
new
\
SimpleSAML\Error\Error
(
'WRONGUSERPASS'
);
}
/* Extract attributes. We allow the resultset to consist of multiple rows. Attributes
* which are present in more than one row will become multivalued. NULL values and
* duplicate values will be skipped. All values will be converted to strings.
*/
$attributes
=
array
();
foreach
(
$data
as
$row
)
{
foreach
(
$row
as
$name
=>
$value
)
{
if
(
$value
===
NULL
)
{
continue
;
}
if
(
$name
===
$this
->
hash_column
)
{
/* Don't add password hash to attributes */
continue
;
}
$value
=
(
string
)
$value
;
if
(
!
array_key_exists
(
$name
,
$attributes
))
{
$attributes
[
$name
]
=
array
();
}
if
(
in_array
(
$value
,
$attributes
[
$name
],
TRUE
))
{
/* Value already exists in attribute. */
continue
;
}
$attributes
[
$name
][]
=
$value
;
}
}
\
SimpleSAML\Logger
::
info
(
'sqlauthBcrypt:'
.
$this
->
authId
.
': Attributes: '
.
implode
(
','
,
array_keys
(
$attributes
)));
return
$attributes
;
}
}
?>
\ No newline at end of file
?>
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment