Plugin para hacer una conexión oAuth a GitHub (o Twitter, o LinkedIn)

  • 10/10/2013

Encontre un artículo muy interesante sobre como hacer una conexión autentificada entre GitHub y WordPress. Como había unas cuantas cosas raras en el código, empecé a reescribirlo. El listado de cambios esta en la versión completa en Gist.

Mejor concentrarse en como funciona ahora. La base del plugin es como siempre Plugin Class Demo, by toscho:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php
add_action(
    'plugins_loaded',
    array ( B5F_GitHub_For_WordPress::get_instance(), 'plugin_setup' )
);
 
class B5F_GitHub_For_WordPress
{
    protected static $instance = NULL;
    public $plugin_url = '';
    public $plugin_path = '';
    public $plugin_admin_url = 'index.php?page=my-github-connect';
 
    /* Constructor. Intencionalmente blanco y publico. */
    public function __construct() { }
 
    public static function get_instance()
    {
        NULL === self::$instance and self::$instance = new self;
        return self::$instance;
    }
 
    public function plugin_setup()
    {
        $this->plugin_url = plugins_url( '/', __FILE__ );
        $this->plugin_path = plugin_dir_path( __FILE__ );
        $this->load_language( 'plugin_unique_name' );
 
        $this->check_oauth();
        add_shortcode( 'github', array( $this, 'render_shortcode' ) );
        add_action( 'admin_menu', array( $this, 'admin_menu' ) );
    }
}

Ese es el bloque básico y que empieza en un punto seguro, plugins_loaded. Tenemos unas cuantas properties (las variables) y los 3 métodos básicos. El que nos interesa es plugin_setup, desde ahí lanzamos todos nuestros hooks. Si hace falta consultar nuestro plugin desde cualquier punto de WordPress, llamamos B5F_GitHub_For_WordPress::get_instance()->plugin_url, p.ej.

En el setup, verficamos si hay una llamada de oAuth. Tenemos el Shortcode, usado en la página de nuestro plugin y también en cualquier post/página. Y registramos el manú del plugin.


Nuestro menú añade una página al Escritorio y en ella confirmamos que hubo un submit. Tenemos un nonce para asegurarnos que el procesamiento del <form> proviene de nuestra página. Luego, sí la Clave y Secreto han sido suministrados, mostrarmos el botón de Authenticate. Y el do_shortcode va a imprimir los resultados de la consulta a GitHub si hay un $token guardado (eso lo vemos enseguida).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<?php
public function admin_menu()
{
	add_dashboard_page(
		'GitHub Options', 
		'GitHub', 
		'manage_options', 
		'my-github-connect', 
		array( $this, 'admin_page' )
	);
}
 
public function admin_page()
{
	if( $_SERVER["REQUEST_METHOD"] == "POST" )
	{
		if ( 
		    isset( $_POST['b5f_gpfw_nonce'] ) 
		    &&  wp_verify_nonce( $_POST['b5f_gpfw_nonce'], plugin_basename( __FILE__ ) ) 
		    )
		{
			if( isset( $_POST['api_key'] ) )
				update_option( 'GITHUB_API_KEY', $_POST['api_key'] );
			if( isset( $_POST['api_secret_key'] ) )
				update_option( 'GITHUB_API_SECRET_KEY', $_POST['api_secret_key'] );
		}
	}
	?>
	<div class="github-admin-options">
	<h1>GitHub Options</h1>
	<form name="options" method="POST" action="<?php echo $_SERVER['REQUEST_URI']; ?>">
	<?php wp_nonce_field( plugin_basename( __FILE__ ), 'b5f_gpfw_nonce' ); ?>
		<!-- html con los inputs de texto y boton de guardar -->
		<?php
		$state = base64_encode( time() );
		$redirect = admin_url( $this->plugin_admin_url );
		$api_key = get_option( 'GITHUB_API_KEY' );
		$api_secret = get_option( 'GITHUB_API_SECRET_KEY' );
		$token = get_option( 'GITHUB_AUTHENTICATION_TOKEN' );
		if( $api_key && $api_secret && !$token )
		{
			$api_url = "https://github.com/login/oauth/authorize?client_id=$api_key&scope=&state=$state&redirect_uri=$redirect";
			?><a class="button-primary" type="button" href="<?php echo $api_url; ?>">Authenticate</a><?php
		}
		?>
	</form>
	<?php echo do_shortcode( '[github]' ); ?>
	</div>
	<?php
}

Primero, creamos un App en GitHub, y rellenamos nuestro sitio web y la página del plugin:

Github plugin for wordpress

Y luego en nuestra página ponemos el Client ID y Client Secret. Después de guardarlos, nos aparece el botón de Authenticate.

Github plugin for wordpress admin


El chequeo del oAuth solo se hace si estamos en nuestra página, y luego si hay un code siendo enviado en la URL. Si está todo bien, guardamos la opción y redireccionamos para la misma página de nuevo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
private function check_oauth()
{
    if( !isset( $_GET['page'] ) || 'my-github-connect' != $_GET['page'] )
        return;
 
    if( $_SERVER["REQUEST_METHOD"] == "GET" && isset( $_GET['code'] ) )
    {
        $redirect = admin_url( $this->plugin_admin_url );
        $api_key = get_option( 'GITHUB_API_KEY' );
        $api_secret = get_option( 'GITHUB_API_SECRET_KEY' );
        $args = array( /* ver plugin para los argumentos */ );
        add_filter( 'https_ssl_verify', '__return_false' );
        $response = wp_remote_post( 'https://github.com/login/oauth/access_token', $args );
        $keys = json_decode( $response['body'] );
        if( $keys )
            update_option( 'GITHUB_AUTHENTICATION_TOKEN', $keys->access_token );
 
        wp_redirect( admin_url( $this->plugin_admin_url ) );
        exit;
    }
}

Sí ha ido todo bien, el botón de Authenticate nos lleva a esta página:

Github plugin for wordpress oauth


Después de autorizar nuestra aplicación, somos redireccionados a la página de nuestro plugin y el Shortcode finalmente funciona:

Github plugin for wordpress admin with oauth

Aquí vemos que el Shortcode solo funciona si tenemos un Token. Usando wp_enqueue_style dentro de la función garantizamos que solo cargará la hoja de estilos cuando el Shortcode esté activo. Y usamos un transiente para guardar los resultados en caché. El filtro de SSL es para prevenir errores en algunos shared hostings.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
public function render_shortcode( $atts )
{
	$token = get_option( 'GITHUB_AUTHENTICATION_TOKEN' );
	if( !$token )
		return;
 
	wp_enqueue_style( 'github-style', plugins_url( '/style.css', __FILE__ ) );			
	add_filter( 'https_ssl_verify', '__return_false' );
	$api_url = "https://api.github.com/user?access_token=$token";
	$json = get_transient( 'github_user' );
	if( !$json )
	{
		$response = wp_remote_get( $api_url );
		$json = json_decode( $response['body'] );
		set_transient( 'github_user', $json, 60*60 );
	}
	$return = construir_html_a_partir_de_array( $json );
	return $return;
}

Descargar el código completo en Gist. La misma técnica puede ser usada con Twitter e LinkedIn. En esos otros dos artículos de Developer Drive hay que sacar los fundamentos y aplicarlos en la nueva base.

Y de brindis ;), la versión avanzada del plugin en GitHub, que se puede ver en acción en este enlace. Mis repos están en verde, y los forked en gris. Hay también un listado de mis Gists y otro con mis Repos favoritos.


Leave a reply

This entry was posted in Plugins, Tutorial, WordPress on .