Meraki Social Login with Linkedin

How to use Linkedin account to login company guest network?

That’s the question.

Most commonly companies use static passwords or pre/self registration in guest networks. Cisco Meraki guest access can give you much more information about your guests (eg. name, email, photo and current position). In this article I tell you how-to use Cisco Meraki’s social login feature. I’d like to thank phpgang for basic idea for oAuth2 authentication.

I did some search in Google and I did not find good examples how-to use Cisco Meraki and php together with social login. Here is one example how-to use those.

What if you guest-network login layout looks something like this instead of username/password fields? What if you can advertise your products in guest access page?

First you need to development account in Linkedin and give some permission to your php-code.

https://www.linkedin.com/developer/apps/

You need to get Client Id, Client Secret and you must to know your server dns name. Remember use SSL secured site, with real certificates.

You must also need to configure Meraki walled garden to allow access to certain sites (Linkedin and your www-server) without authentication.

After this is done you can put your php-code together. This code is still under dev and contains some bugs, idiotism etc, but it works.

Create config.php file. This file include your Linkedin app client id and client secret, so keep it private.

<?php
    $client_id = "client_id_here"; // enter your client id
    $client_secret = "client_secret_here"; // enter your client secret
    $redirect_uri = "https://acme_jetlag_url_here/callback.php"; // enter your redirect url
?>

Next you need to create index.php file. Your client will first see this page.

<!DOCTYPE html>
<html>
<head>
<style>

div.container {
    width: 100%;
    border: 1px solid gray;
}

div {
    background-color: white;
}

header, footer {
    padding: 1em;
    color: white;
    background-color: #3A454A;
    clear: left;
    text-align: center;
}

nav {
    float: left;
    max-width: 160px;
    margin: 0;
    padding: 1em;
}

nav ul {
    list-style-type: none;
    padding: 0;
}

nav ul a {
    text-decoration: none;
}

article {
    margin-left: 270px;
    border-left: 1px solid gray;
    padding: 1em;
    overflow: hidden;
}

body  {
    background-image: url("showroom.jpg");
    background-color: #ffffff;
}

img {
    width:100%;
}

</style>
</head>

<body>
<div class="container">
<header>
   <h1>Social Login</h1>
</header>

<nav>
    <p>Sign in using your Linkedin account.</p>

<?php
   session_start();
   $base_grant_url = urldecode($_GET['base_grant_url']);
   $user_continue_url = urldecode($_GET['user_continue_url']);
   $override_continue_url = 'https://www.hacknetwork.org';
   $override_the_users_request = false;

   echo '<a href="login.php"><img src="Linkedin_login.png" alt="Linkedin login button" style="width:200px;"></a>';
      if ($override_the_users_request) {
        $grant_url = $base_grant_url . "?continue_url=" . urlencode($override_continue_url) ."&duration=28800";
      } else {
        $grant_url = $base_grant_url . "?continue_url=" . urlencode($user_continue_url) ."&duration=28800";
      }

      $_SESSION['grant_url'] = $grant_url;
      $_SESSION['user_continue_url'] = $user_continue_url;
      $_SESSION['base_grant_url'] = $base_grant_url;
?>

</nav>
<article>
  <h1>Guest Network</h1>
  <p>Lorium ipslum, blah, blah. Session timeout is 8 hour.</p>
  <br><p>Guest network is using Meraki techology and custom social login functions.</p>
</article>
<footer>Under GPL. Ville Leinonen/Atea Finland</footer>
</div>
</body>
</html>

When guest clicks Linkedin image, user will redirected to Linkedin authentication page. This page is provided by Linkedin, so we don’t see guest passwords.

After successfully login Linkedin will send data back to callback.php page.

<?php
// Replace this in next version -->
function post_curl($url,$param="")
{
    $ch = curl_init();
    curl_setopt($ch,CURLOPT_URL,$url);
    if($param!="")
        curl_setopt($ch,CURLOPT_POSTFIELDS,$param);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    $result = curl_exec($ch);
    curl_close($ch);
    return $result;
}
// <---

    session_start();
    if( isset($_SESSION['user_info']) or !isset($_SESSION['login']) ){ // if user is logged in
        header("location: index.php"); // redirect user to index page
        return false;
    }
    include 'config.php'; // include app data
if(isset($_GET['code'])) // get code after authorization
{
    $url = 'https://www.linkedin.com/uas/oauth2/accessToken';
    $param = 'grant_type=authorization_code&code='.$_GET['code'].'&redirect_uri='.$redirect_uri.'&client_id='.$client_id.'&client_secret='.$client_secret;
    $return = (json_decode(post_curl($url,$param),true));
       $url = 'https://api.linkedin.com/v1/people/~:(id,firstName,lastName,pictureUrls::(original),headline,publicProfileUrl,location,industry,positions,email-address)?format=json&oauth2_access_token='.$return['access_token'];
       $obj = json_decode(file_get_contents($url), true);
}
    $_SESSION['user_info'] = $obj;
      $grant_url = $_SESSION['grant_url'];
      $user_continue_url = $_SESSION['user_continue_url'];
      $base_grant_url = $_SESSION['base_grant_url'];
      $_SESSION['grant_url'] = $grant_url;
      $_SESSION['user_continue_url'] = $user_continue_url;
      $_SESSION['base_grant_url'] = $base_grant_url;

    header("location: afterlogin.php");
?>

Site callback.php will redirect client to afterlogin.php page. Guest still need to click link to get access.

<!DOCTYPE html>
<html>
<head>
<style>

div.container {
    width: 100%;
    border: 1px solid gray;
}

div {
    background-color: white;
}

header, footer {
    padding: 1em;
    color: white;
    background-color: #3A454A;
    clear: left;
    text-align: center;
}

nav {
    float: left;
    max-width: 260px;
    margin: 0;
    padding: 1em;
}

nav ul {
    list-style-type: none;
    padding: 0;
}

nav ul a {
    text-decoration: none;
}

article {
    margin-left: 270px;
    border-left: 1px solid gray;
    padding: 1em;
    overflow: hidden;
}

body  {
    background-image: url("showroom.jpg");
    background-color: #ffffff;
}

img {
    width:100%;
}

</style>
</head>
<body>
<div class="container">
<header>
   <h1>Login Success</h1>
</header>
<nav>
<?php
    session_start();
    if( isset($_SESSION['user_info']) ){ // if user is logged in
        $user_info = $_SESSION['user_info'];
        $grant_url = $_SESSION['grant_url'];
        $user_continue_url = $_SESSION['user_continue_url'];

        $override_continue_url = 'https://www.hacknetwork.org';
        $base_grant_url = $_SESSION['base_grant_url'];
?>
        <p>Continue to Internet <a href="<?php print $grant_url ?>">Click here</a>.</p>
        <?php
    }

    else{ // if user is not logged in
       header("location: index.php");
    }
?>

</nav>
<article>
    <h1>Welcome <?php echo $user_info["firstName"]; ?> <?php echo $user_info["lastName"]; ?></h1>
    <p>Click left side link continue to the Internet.</p>
    <p>Use your daily ACME coupon code for get free cup of coffee: <b>Free4Cf33</b></p>
    <p>Get our latest offers from Atea eSHOP (eshop.atea.fi)</p>
</article>
<footer>Under GPL. Ville Leinonen/Atea Finland</footer>
</div>
</body>
</html>

If everything goes fine you get information for your guest users.