Skip to content

Commit d7161f1

Browse files
committed
Initial import
1 parent e795ead commit d7161f1

File tree

12 files changed

+463
-0
lines changed

12 files changed

+463
-0
lines changed

.codecov.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
coverage:
2+
status:
3+
project: yes
4+
5+
comment:
6+
layout: "diff"
7+
behavior: once
8+
require_changes: true
9+
require_base: no
10+
require_head: yes
11+
branches: null

.php_cs.dist

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
$finder = PhpCsFixer\Finder::create()
3+
->in([
4+
__DIR__ . '/lib',
5+
__DIR__ . '/tests',
6+
__DIR__ . '/www',
7+
])
8+
;
9+
return PhpCsFixer\Config::create()
10+
->setRules([
11+
'@PSR2' => true,
12+
'@PSR4' => true,
13+
'@PSR5' => true,
14+
])
15+
->setFinder($finder)
16+
;

.travis.yml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
sudo: required
2+
3+
language: php
4+
5+
php:
6+
- 5.5
7+
- 5.6
8+
- 7.0
9+
- 7.1
10+
- 7.2
11+
- 7.3
12+
13+
env:
14+
- SIMPLESAMLPHP_VERSION=1.17.*
15+
16+
matrix:
17+
include:
18+
- php: 5.6
19+
env: SIMPLESAMLPHP_VERSION=dev-master
20+
- php: 7.0
21+
env: SIMPLESAMLPHP_VERSION=dev-master
22+
- php: 7.1
23+
env: SIMPLESAMLPHP_VERSION=dev-master
24+
- php: 7.2
25+
env: SIMPLESAMLPHP_VERSION=dev-master
26+
- php: 7.3
27+
env: SIMPLESAMLPHP_VERSION=dev-master
28+
allow_failures:
29+
- env: SIMPLESAMLPHP_VERSION=dev-master
30+
- php: 7.3
31+
- php: hhvm
32+
33+
before_script:
34+
- composer require "simplesamlphp/simplesamlphp:${SIMPLESAMLPHP_VERSION}" --no-update
35+
- composer update --no-interaction
36+
- if [[ "$TRAVIS_PHP_VERSION" == "7.3" ]]; then composer require --dev vimeo/psalm; fi
37+
38+
script:
39+
- bin/check-syntax.sh
40+
- if [[ "$TRAVIS_PHP_VERSION" == "5.6" ]]; then php vendor/phpunit/phpunit/phpunit; else php vendor/phpunit/phpunit/phpunit --no-coverage; fi
41+
- if [[ "$TRAVIS_PHP_VERSION" == "7.3" ]]; then vendor/bin/psalm; fi
42+
43+
after_success:
44+
# Codecov, need to edit bash uploader for incorrect TRAVIS_PYTHON_VERSION environment variable matching, at least until codecov/codecov-bash#133 is resolved
45+
- curl -s https://codecov.io/bash > .codecov
46+
- sed -i -e 's/TRAVIS_.*_VERSION/^TRAVIS_.*_VERSION=/' .codecov
47+
- chmod +x .codecov
48+
- if [[ $TRAVIS_PHP_VERSION == "5.6" ]]; then ./.codecov -X gcov; fi
49+
# - if [[ "$TRAVIS_PHP_VERSION" == "5.6" ]]; then bash <(curl -s https://codecov.io/bash); fi

bin/check-syntax.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/usr/bin/env bash
2+
3+
PHP='/usr/bin/env php'
4+
RETURN=0
5+
6+
# check PHP files
7+
for FILE in `find lib www -name "*.php"`; do
8+
$PHP -l $FILE > /dev/null 2>&1
9+
if [ $? -ne 0 ]; then
10+
echo "Syntax check failed for ${FILE}"
11+
RETURN=`expr ${RETURN} + 1`
12+
fi
13+
done
14+
15+
exit $RETURN

composer.json

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"name": "simplesamlphp/simplesamlphp-module-authtwitter",
3+
"description": "A module that is able to perform authentication against Twitter",
4+
"type": "simplesamlphp-module",
5+
"keywords": ["simplesamlphp", "twitter"],
6+
"license": "LGPL-3.0-or-later",
7+
"authors": [
8+
{
9+
"name": "Olav Morken",
10+
"email": "olavmrk@gmail.com"
11+
},
12+
{
13+
"name": "Tim van Dijen",
14+
"email": "tvdijen@gmail.com"
15+
}
16+
],
17+
"config": {
18+
"preferred-install": {
19+
"simplesamlphp/simplesamlphp": "source",
20+
"*": "dist"
21+
}
22+
},
23+
"autoload": {
24+
"psr-4": {
25+
"SimpleSAML\\modules\\authtwitter\\": "lib/"
26+
}
27+
},
28+
"autoload-dev": {
29+
"psr-4": {
30+
"Tests\\SimpleSAML\\modules\\authtwitter\\TestFiles\\": "tests/files",
31+
"SimpleSAML\\Test\\Utils\\": "vendor/simplesamlphp/simplesamlphp/tests/Utils"
32+
}
33+
},
34+
"require": {
35+
"php": ">=5.5",
36+
"simplesamlphp/composer-module-installer": "~1.0",
37+
"simplesamlphp/simplesamlphp-module-oauth": "~1.0",
38+
"webmozart/assert": "^1.4"
39+
},
40+
"require-dev": {
41+
"simplesamlphp/simplesamlphp": "^1.17",
42+
"phpunit/phpunit": "~4.8.35"
43+
},
44+
"support": {
45+
"issues": "https://github.com/tvdijen/simplesamlphp-module-authtwitter/issues",
46+
"source": "https://github.com/tvdijen/simplesamlphp-module-authtwitter"
47+
}
48+
}

default-enable

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
This file indicates that the default state of this module
2+
is enabled. To enable, create a file named disable in the
3+
same directory as this file.

docs/oauthtwitter.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
Using the Twitter authentication source with SimpleSAMLphp
2+
==========================================================
3+
4+
Remember to configure `authsources.php`, with both Consumer key and secret.
5+
6+
To get an API key and a secret, register the application at:
7+
8+
* <http://twitter.com/oauth_clients>
9+
10+
Set the callback URL to be:
11+
12+
* `http://sp.example.org/simplesaml/module.php/authtwitter/linkback.php`
13+
14+
Replace `sp.example.org` with your hostname.
15+
16+
## Testing authentication
17+
18+
On the SimpleSAMLphp frontpage, go to the *Authentication* tab, and use the link:
19+
20+
* *Test configured authentication sources*
21+
22+
Then choose the *twitter* authentication source.
23+
24+
Expected behaviour would then be that you are sent to twitter, and asked to login:
25+
26+
![](http://clippings.erlang.no/ZZ2EE26BF6.jpg)
27+
28+
The first time a user uses your application to login, he/she is asked for consent:
29+
30+
![](http://clippings.erlang.no/ZZ6B18B5D9.jpg)
31+
32+
You will then be authenticated in SimpleSAMLphp and see an attribute set similar to this:
33+
34+
![](http://clippings.erlang.no/ZZ74A6835E.jpg)
35+

lib/Auth/Source/Twitter.php

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
<?php
2+
3+
namespace SimpleSAML\Module\authtwitter\Auth\Source;
4+
5+
use Webmozart\Assert\Assert;
6+
7+
$default = dirname(dirname(dirname(dirname(dirname(__FILE__))))).'/oauth/libextinc/OAuth.php';
8+
$travis = dirname(dirname(dirname(dirname(__FILE__)))).'/vendor/simplesamlphp/simplesamlphp/modules/oauth/libextinc/OAuth.php';
9+
10+
if (file_exists($default)) {
11+
require_once($default);
12+
} else if (file_exists($travis)) {
13+
require_once($travis);
14+
} else {
15+
// Probably codecov, but we can't raise an exception here or Travis will fail
16+
}
17+
18+
/**
19+
* Authenticate using Twitter.
20+
*
21+
* @author Andreas Åkre Solberg, UNINETT AS.
22+
* @package SimpleSAMLphp
23+
*/
24+
25+
class Twitter extends \SimpleSAML\Auth\Source
26+
{
27+
/**
28+
* The string used to identify our states.
29+
*/
30+
const STAGE_INIT = 'twitter:init';
31+
32+
/**
33+
* The key of the AuthId field in the state.
34+
*/
35+
const AUTHID = 'twitter:AuthId';
36+
37+
/**
38+
* @var string
39+
*/
40+
private $key;
41+
42+
/**
43+
* @var string
44+
*/
45+
private $secret;
46+
47+
/**
48+
* @var bool
49+
*/
50+
private $force_login;
51+
52+
/**
53+
* @var bool
54+
*/
55+
private $include_email;
56+
57+
/**
58+
* Constructor for this authentication source.
59+
*
60+
* @param array $info Information about this authentication source.
61+
* @param array $config Configuration.
62+
*/
63+
public function __construct($info, $config)
64+
{
65+
Assert::isArray($info);
66+
Assert::isArray($config);
67+
68+
// Call the parent constructor first, as required by the interface
69+
parent::__construct($info, $config);
70+
71+
$configObject = \SimpleSAML\Configuration::loadFromArray(
72+
$config,
73+
'authsources['.var_export($this->authId, true).']'
74+
);
75+
76+
$this->key = $configObject->getString('key');
77+
$this->secret = $configObject->getString('secret');
78+
$this->force_login = $configObject->getBoolean('force_login', false);
79+
$this->include_email = $configObject->getBoolean('include_email', false);
80+
}
81+
82+
/**
83+
* Log-in using Twitter platform
84+
*
85+
* @param array &$state Information about the current authentication.
86+
* @return void
87+
*/
88+
public function authenticate(&$state)
89+
{
90+
Assert::isArray($state);
91+
92+
// We are going to need the authId in order to retrieve this authentication source later
93+
$state[self::AUTHID] = $this->authId;
94+
95+
$stateID = \SimpleSAML\Auth\State::saveState($state, self::STAGE_INIT);
96+
97+
$consumer = new \SimpleSAML\Module\oauth\Consumer($this->key, $this->secret);
98+
// Get the request token
99+
$linkback = \SimpleSAML\Module::getModuleURL('authtwitter/linkback.php', ['AuthState' => $stateID]);
100+
$requestToken = $consumer->getRequestToken(
101+
'https://api.twitter.com/oauth/request_token',
102+
['oauth_callback' => $linkback]
103+
);
104+
\SimpleSAML\Logger::debug("Got a request token from the OAuth service provider [".
105+
$requestToken->key."] with the secret [".$requestToken->secret."]");
106+
107+
$state['authtwitter:authdata:requestToken'] = $requestToken;
108+
\SimpleSAML\Auth\State::saveState($state, self::STAGE_INIT);
109+
110+
// Authorize the request token
111+
$url = 'https://api.twitter.com/oauth/authenticate';
112+
if ($this->force_login) {
113+
$url = \SimpleSAML\Utils\HTTP::addURLParameters($url, ['force_login' => 'true']);
114+
}
115+
$consumer->getAuthorizeRequest($url, $requestToken);
116+
}
117+
118+
119+
/**
120+
* @param array &$state
121+
* @return void
122+
*/
123+
public function finalStep(&$state)
124+
{
125+
$requestToken = $state['authtwitter:authdata:requestToken'];
126+
$parameters = [];
127+
128+
if (!isset($_REQUEST['oauth_token'])) {
129+
throw new \SimpleSAML\Error\BadRequest("Missing oauth_token parameter.");
130+
}
131+
if ($requestToken->key !== (string) $_REQUEST['oauth_token']) {
132+
throw new \SimpleSAML\Error\BadRequest("Invalid oauth_token parameter.");
133+
}
134+
135+
if (!isset($_REQUEST['oauth_verifier'])) {
136+
throw new \SimpleSAML\Error\BadRequest("Missing oauth_verifier parameter.");
137+
}
138+
$parameters['oauth_verifier'] = (string) $_REQUEST['oauth_verifier'];
139+
140+
$consumer = new \SimpleSAML\Module\oauth\Consumer($this->key, $this->secret);
141+
142+
\SimpleSAML\Logger::debug("oauth: Using this request token [".
143+
$requestToken->key."] with the secret [".$requestToken->secret."]");
144+
145+
// Replace the request token with an access token
146+
$accessToken = $consumer->getAccessToken(
147+
'https://api.twitter.com/oauth/access_token',
148+
$requestToken,
149+
$parameters
150+
);
151+
\SimpleSAML\Logger::debug("Got an access token from the OAuth service provider [".
152+
$accessToken->key."] with the secret [".$accessToken->secret."]");
153+
154+
$verify_credentials_url = 'https://api.twitter.com/1.1/account/verify_credentials.json';
155+
if ($this->include_email) {
156+
$verify_credentials_url = $verify_credentials_url.'?include_email=true';
157+
}
158+
$userdata = $consumer->getUserInfo($verify_credentials_url, $accessToken);
159+
160+
if (!isset($userdata['id_str']) || !isset($userdata['screen_name'])) {
161+
throw new \SimpleSAML\Error\AuthSource(
162+
$this->authId,
163+
'Authentication error: id_str and screen_name not set.'
164+
);
165+
}
166+
167+
$attributes = [];
168+
foreach ($userdata as $key => $value) {
169+
if (is_string($value)) {
170+
$attributes['twitter.'.$key] = [(string) $value];
171+
}
172+
}
173+
174+
$attributes['twitter_at_screen_name'] = ['@'.$userdata['screen_name']];
175+
$attributes['twitter_screen_n_realm'] = [$userdata['screen_name'].'@twitter.com'];
176+
$attributes['twitter_targetedID'] = ['http://twitter.com!'.$userdata['id_str']];
177+
178+
$state['Attributes'] = $attributes;
179+
}
180+
}

phpunit.xml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<phpunit bootstrap="tests/bootstrap.php">
3+
<testsuites>
4+
<testsuite name="The project's test suite">
5+
<directory>tests/</directory>
6+
</testsuite>
7+
</testsuites>
8+
<filter>
9+
<whitelist processUncoveredFilesFromWhitelist="true">
10+
<directory suffix=".php">./lib</directory>
11+
</whitelist>
12+
</filter>
13+
<logging>
14+
<log type="coverage-text" target="php://stdout" showUncoveredFiles="true" />
15+
<log type="coverage-html" target="build/coverage" title="PHP Coveralls" charset="UTF-8" yui="true" highlight="true" lowUpperBound="35" highLowerBound="70" />
16+
<log type="coverage-clover" target="build/logs/clover.xml" />
17+
</logging>
18+
</phpunit>
19+

0 commit comments

Comments
 (0)