Plugin Directory

Changeset 2184906


Ignore:
Timestamp:
11/02/2019 11:52:37 AM (6 years ago)
Author:
shfarr
Message:

moving to version 2.0

Location:
identity-plus/trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • identity-plus/trunk/lib/comments.php

    r1535864 r2184906  
    6464function identity_plus_send_trust($cert_id, $amount, $intrusion_reference = NULL){
    6565        $options = get_option( 'identity_plus_settings' );
    66         if(!empty($options) && isset($options['cert-file']) && isset($options['cert-password'])){
    67                 $identity_plus_api = new Identity_Plus_API(file_get_contents($options['cert-file']), $options['cert-password']);
     66        if(!empty($options) && isset($options['cert-data']) && isset($options['cert-password'])){
     67                $identity_plus_api = new Identity_Plus_API(base64_decode($options['cert-data']), $options['cert-password']);
    6868
    6969                if(isset($identity_plus_api) && $identity_plus_api != NULL){
     
    8686function identity_plus_revoke_intrusion($reference){
    8787        $options = get_option( 'identity_plus_settings' );
    88         if(!empty($options) && isset($options['cert-file']) && isset($options['cert-password'])){
    89                 $identity_plus_api = new Identity_Plus_API(file_get_contents($options['cert-file']), $options['cert-password']);
     88        if(!empty($options) && isset($options['cert-data']) && isset($options['cert-password'])){
     89                $identity_plus_api = new Identity_Plus_API(base64_decode($options['cert-data']), $options['cert-password']);
    9090               
    9191                if(isset($identity_plus_api) && $identity_plus_api != NULL){
     
    107107function identity_plus_send_intrusion($cert_id){
    108108        $options = get_option( 'identity_plus_settings' );
    109         if(!empty($options) && isset($options['cert-file']) && isset($options['cert-password'])){
    110                 $identity_plus_api = new Identity_Plus_API(file_get_contents($options['cert-file']), $options['cert-password']);
     109        if(!empty($options) && isset($options['cert-data']) && isset($options['cert-password'])){
     110                $identity_plus_api = new Identity_Plus_API(base64_decode($options['cert-data']), $options['cert-password']);
    111111               
    112112                if(isset($identity_plus_api) && $identity_plus_api != NULL){
     
    117117                                Identity_Plus_Utils::here().Identity_Plus_Utils::query());
    118118
    119                         // careful, the comment is not commeing from the user that approves it
     119                        // careful, the comment is not comming from the user that approves it
    120120                        add_option("identity-plus/".$cert_id, "expire");
    121121                        return $reference;
     
    133133function identity_plus_hide_comments(){
    134134        $options = get_option( 'identity_plus_settings' );
    135         if(!empty($options) && isset($options['cert-file']) && isset($options['cert-password']) && isset($options['comments']) && $options['comments']){
     135        if(!empty($options) && isset($options['cert-data']) && isset($options['cert-password']) && isset($options['comments']) && $options['comments']){
    136136                if(!isset($_SESSION['identity-plus-anonymous-id']) || $_SESSION['identity-plus-anonymous-id'] == 'N/A'){
    137137                        ?><style>#commentform{display:none;}</style><?php
     
    149149   
    150150    if(isset($options['comments']) && $options['comments']){
    151                 $identity_plus_api = new Identity_Plus_API(file_get_contents($options['cert-file']), $options['cert-password']);
     151                $identity_plus_api = new Identity_Plus_API(base64_decode($options['cert-data']), $options['cert-password']);
    152152       
    153153                $message = isset($_SESSION['identity-plus-anonymous-id']) && $_SESSION['identity-plus-anonymous-id'] != 'N/A' ?
  • identity-plus/trunk/lib/identity_plus/Identity_Plus_API.php

    r2032170 r2184906  
    2020use identity_plus\api\communication\Intent;
    2121use identity_plus\api\communication\Intent_Reference;
     22use identity_plus\api\communication\Service_Agent_Identity_Request;
     23use identity_plus\api\communication\Service_Agent_Identity;
    2224
    2325/*
     
    6264 */
    6365class Identity_Plus_API {
    64     const api_endpoint = "https://api.identity.plus/v1";
    65     const validation_endpoint = "https://signon.identity.plus";
    66     // const api_endpoint = "https://dev-api.identity.plus:8443/v1";
    67     // const validation_endpoint = "https://my.dev.identity.plus:8443";
     66    const HOME = "identity.plus";
     67    // const HOME = "local.stefanfarr.identityplus.app";
     68    const api_endpoint = "https://api." . self::HOME . "/v1";
     69    const validation_endpoint = "https://signon." . self::HOME;
    6870   
    6971    public $cert_details;
     
    8789            $this->cert_details = openssl_x509_parse($this->cert);
    8890        }
    89         else return NULL;
     91        else{
     92            error_log("Unable to load key material from pkcs12 store.");
     93            return NULL;
     94        }
    9095    }
    9196   
     
    122127     */
    123128    public function certificate_validation_endpoint($return_url = NULL){
    124             if($return_url == NULL){
     129        if($return_url == NULL){
    125130            session_start();
    126131            $_SESSION['identity-plus-return-query'] =  Identity_Plus_Utils::here().Identity_Plus_Utils::query();
     
    131136        return self::validation_endpoint.'/' . $intent->value;
    132137    }
    133    
     138
     139    /**
     140     * Renew Identity Plus Service Agent ID
     141     *
     142     * @param unknown $service_domain the service to which the agent belongs. The service the current agent represents must be administrator
     143     * over the target service. By default it is the service the agent belongs (self renew)
     144     * @param unknown $agent_name the name of the agent, if not provided it will be taken from the certificate (self renew)
     145     * @return if all goes well an updated Service_Agent_Identity otherwise a Simple_Response containing an error code
     146     */
     147    public function issue_service_agent_identity($service_domain, $agent_name){
     148        $request = new Service_Agent_Identity_Request($service_domain, $agent_name);
     149        return $this->issue_call($request, "PUT");
     150    }
     151   
     152    public function register_service($register_intent, $agent_name){
     153        $args = array(
     154            "authorization" => $register_intent,
     155            "agent-name" => $agent_name
     156        );
     157
     158        $request = array(
     159            "operation" => "issue-service-agent-certificate",
     160            "args" => $args
     161        );
     162       
     163        $call = curl_init(self::validation_endpoint . "/api/v1");
     164       
     165        // curl_setopt($call, CURLOPT_VERBOSE, true);
     166        curl_setopt($call, CURLOPT_URL, self::validation_endpoint . "/api/v1");
     167        curl_setopt($call, CURLOPT_CUSTOMREQUEST, "POST");
     168        curl_setopt($call, CURLOPT_POSTFIELDS, json_encode($request));
     169        curl_setopt($call, CURLOPT_RETURNTRANSFER, true);
     170       
     171        curl_setopt($call, CURLOPT_SSL_VERIFYPEER, false);
     172        curl_setopt($call, CURLOPT_SSL_VERIFYHOST, false);
     173       
     174        $result = curl_exec($call);
     175               
     176        curl_close ($call);
     177       
     178        return self::decode(json_decode($result));
     179    }
     180   
    134181    /**
    135182     * Initiates an binding API Call which will bind the local user to the identity + account with the given anonymoys id.
     
    278325        curl_setopt($call, CURLOPT_POSTFIELDS, $request->to_json());
    279326        curl_setopt($call, CURLOPT_RETURNTRANSFER, true);
    280        
     327       
     328        curl_setopt($call, CURLOPT_SSL_VERIFYPEER, false);
     329        curl_setopt($call, CURLOPT_SSL_VERIFYHOST, false);
     330
    281331        $result = curl_exec($call);
    282332       
     
    305355        return $encrypted;
    306356    }
    307    
    308     /**
    309      * An decryption function wrapper using the API certificate's private key
    310      *
    311      * @param unknown $data: data to be decrypted. It is expected to be encrypted with the certificate's public key
    312      * @return decrypted data
    313      */
    314     public function decrypt($data){
    315         openssl_private_decrypt($data, $decrypted, $this->private_key);
    316         return $decrypted;
    317     }
     357
    318358
    319359    /**
     
    322362     */
    323363    public static function decode($data){
     364        error_log('------------------\n'.json_encode($data).'------------------\n');
     365       
    324366        if(property_exists($data, 'Identity-Profile')) return new Identity_Profile($data->{'Identity-Profile'});
    325367        else if(property_exists($data, 'Reference-Number')) return new Reference_Number($data->{'Reference-Number'});
    326368        else if(property_exists($data, 'Anonymous-ID')) return new Anonymous_ID($data->{'Anonymous-ID'});
    327369        else if(property_exists($data, 'Intent-Reference')) return new Intent_Reference($data->{'Intent-Reference'});
     370        else if(property_exists($data, 'Service-Agent-Identity')) return new Service_Agent_Identity($data->{'Service-Agent-Identity'});
    328371        else return new Simple_Response($data->{'Simple-Response'});
    329372    }
     
    348391    }
    349392   
    350    
    351    
    352     /**
    353      * Extract the identity + anonymous id from a returning url.
    354      * This happens upon a redirect-back from Identity +
    355      *
    356      * @param unknown &$http_session, the session variable, so that we don't hard code around session
    357      */
    358     function legacy_http_extract_anonymous_id(&$http_session){
    359         $payload =  Identity_Plus_Utils::base64url_decode($_GET['idp-api-response']);
    360         $response = $this->decrypt($payload);
    361 
    362         $serial_number = Identity_Plus_API::decode(json_decode($response));
    363         if($serial_number instanceof Anonymous_ID){
    364             $http_session['identity-plus-anonymous-id'] = $serial_number->serial_number;
    365         }
    366         else $http_session['identity-plus-anonymous-id'] = 'N/A';
    367    
    368         // clear the identity + id extraction url to eliminate confusion
    369         // and complications
    370         if(!isset($http_session['identity-plus-return-query'])){
    371             $q = Identity_Plus_Utils::query();
    372             $q = substr($q, 0, strpos($q, "idp-api-response=") -1);
    373             $http_session['identity-plus-return-query'] = Identity_Plus_Utils::here().$q;
    374         }
    375     }
    376393}
  • identity-plus/trunk/lib/identity_plus/api/Communication.php

    r1932531 r2184906  
    129129        $this->salt = Identity_Plus_Utils::random_text(16);
    130130    }
    131 
    132     /**
    133      * Empty initializer, it is necessary to initialize to null the public fields.
    134      * The deserializer will override the final modifier and re-initialize the fields
    135      * with the proper values
    136      */
    137     public function construct($json){
    138         // restore_object(object);
    139     }
     131}
     132
     133/**
     134 * The Agent Certificate Renewal request is used to issue certificates for Service Agents (Clients).
     135 * This can happen in two ways,:
     136 * either the request is made for a valid previous certificate, in which a renewal procedure is executed,
     137 * or it needs to be performed with an initial secret and then an issuing is performed.
     138 * A service agent can rewnew its own certificate this way, but care must be taken as the previous certificate will be
     139 * revoked uppon issuing the new one.
     140 *
     141 * @author Stefan Harsan Farr
     142 */
     143class Service_Agent_Identity_Request extends API_Request{
     144
     145    /**
     146     * Name of the agent to issue certificate for.
     147     * If the name exists, it will renew, otherwise it will create a new agent
     148     */
     149    public $agent_name;
     150   
     151    /**
     152     * Domain Name of the service where the agent should be issued.
     153     *
     154     * By default (if the domain is not specified), the agent will be created/renewed within the service
     155     * to which the calling agent (the one whose certificate is used to make this call) belongs to.
     156     *
     157     * If the target service is specified, then the calling service (the service to which the calling agent belongs to)
     158     * must have administrative rights in target service. Otherwise this operation will fail
     159     */
     160    public $service_domain;
     161   
     162    public function __construct($service_domain, $agent_name){
     163            $this->service_domain = $service_domain;
     164            $this->agent_name = $agent_name;
     165    }
     166}
     167
     168/**
     169 * The core response for most request containing a reference number
     170 * It comes in response to a call that requires a reference number such as an intrusion report
     171 *
     172 * @author Stefan Harsan Farr
     173 */
     174class Service_Agent_Identity extends API_Response{
     175   
     176    /**
     177     * p12 certificate format
     178     */
     179    public $p12;
     180
     181    /**
     182     * Password for the p12 format
     183     */
     184    public $password;
     185
     186    /**
     187     * PEM encoded certificate
     188     */
     189    public $certificate;
     190   
     191    /**
     192     * PEM encoded private key
     193     */
     194    public $private_key;
     195   
     196   
     197    public function __construct($data){
     198        parent::__construct($data);
     199        $this->p12 = $data->{'p12'};
     200        $this->password = $data->{'password'};
     201        $this->certificate = $data->{'certificate'};
     202        $this->private_key = $data->{'private-key'};
     203    }
    140204}
    141205
     
    279343    public $local_intrusions;
    280344   
     345    /**
     346     * In case this was an out of band authorization, the id of the certificate that made the authorization
     347     */
     348    public $authorizing_certificate;
     349
    281350    /**
    282351     * Empty initializer, it is necessary to initialize to null the public fields.
     
    296365        $this->local_trust = $data->{'local-trust'};
    297366        $this->local_intrusions = $data->{'local-intrusions'};
     367        if(isset($data->{'authorizing-certificate'})) $this->authorizing_certificate = $data->{'authorizing-certificate'};
    298368    }
    299369}
  • identity-plus/trunk/lib/img/idp.svg

    r1920096 r2184906  
    33<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
    44<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
    5      width="128px" height="128px" viewBox="0 0 128 128" style="enable-background:new 0 0 128 128;" xml:space="preserve">
     5     width="415px" height="640px" viewBox="0 0 415 640" enable-background="new 0 0 415 640" xml:space="preserve">
    66<g>
    7     <rect style="fill:#444444;" width="128" height="128"/>
    87    <g>
    9         <g>
    10             <g>
    11                 <path style="fill:#FFFFFF;" d="M22.386,44.303V38.49h4.291v5.813H22.386z M22.386,89.979V52.054h4.325v37.924H22.386z"/>
    12                 <path style="fill:#FFFFFF;" d="M53.432,90.774c-5.052,0-8.991-1.753-11.817-5.26c-2.826-3.506-4.239-8.351-4.239-14.533
    13                     c0-5.813,1.458-10.536,4.377-14.169c2.918-3.633,6.765-5.45,11.54-5.45c2.353,0,4.706,0.508,7.059,1.522
    14                     c2.353,1.016,4.141,2.595,5.363,4.741v-1.142V37.348l4.152-0.381v53.011h-3.563l-0.622-5.709
    15                     c-1.315,2.145-3.098,3.766-5.347,4.861C58.085,90.227,55.785,90.774,53.432,90.774z M53.328,87.384
    16                     c2.146,0,4.025-0.393,5.64-1.177s2.907-1.892,3.875-3.322c0.969-1.43,1.69-3.073,2.163-4.931
    17                     c0.473-1.856,0.709-3.915,0.709-6.177c0-11.28-4.152-16.92-12.456-16.92c-1.961,0-3.691,0.467-5.19,1.401
    18                     c-1.5,0.934-2.682,2.192-3.547,3.771c-0.865,1.581-1.505,3.299-1.92,5.156c-0.416,1.857-0.623,3.813-0.623,5.865
    19                     c0,1.777,0.126,3.443,0.381,5c0.253,1.558,0.668,3.04,1.246,4.446c0.576,1.407,1.292,2.613,2.146,3.616
    20                     c0.853,1.004,1.926,1.8,3.218,2.388C50.259,87.089,51.713,87.384,53.328,87.384z"/>
    21             </g>
    22         </g>
    23         <g>
    24             <g>
    25                 <line style="fill:none;stroke:#4292D3;stroke-width:4.252;stroke-miterlimit:10;" x1="96.4" y1="45.25" x2="96.4" y2="82.75"/>
    26                 <line style="fill:none;stroke:#4292D3;stroke-width:4.252;stroke-miterlimit:10;" x1="115.15" y1="64" x2="77.65" y2="64"/>
    27             </g>
    28         </g>
     8        <path fill="#4596CE" d="M101.563,638.821H3.5L316.177,3.42h97.661L101.563,638.821z"/>
    299    </g>
    3010</g>
    31 <g>
    32 </g>
    33 <g>
    34 </g>
    35 <g>
    36 </g>
    37 <g>
    38 </g>
    39 <g>
    40 </g>
    4111</svg>
  • identity-plus/trunk/lib/initialize.php

    r2032170 r2184906  
    2323add_action('manage_users_custom_column',  'idp_show_user_id_column_content', 10, 3);
    2424
     25function idp_problems($options){
     26    // if(True) return "Manually disabled ...";
     27
     28    if(empty($options) || !isset($options['cert-data']) || !isset($options['cert-password'])){
     29        return "API Certificate is missing! Please follow the steps below to prove ownership of this domain and activate the Identity Plus services.";
     30    }
     31
     32    $cert_store = array();
     33
     34    if(openssl_pkcs12_read (base64_decode($options['cert-data']) , $cert_store , $options['cert-password'])){
     35        $cert_details = openssl_x509_parse($cert_store['cert']);
     36        $now = time();
     37        $days = floor(abs($cert_details['validTo_time_t'] - $now) / 86400);
     38        $all_days = floor(abs($cert_details['validTo_time_t'] - $cert_details['validFrom_time_t']) / 86400);
     39
     40        if(floor($days - $all_days/3) <= 0) return "renew";
     41
     42        // disable Identity Plus if agent certificate expired
     43        // user must go through re-initialziation process
     44        if($cert_details['validTo_time_t'] - $now < 0) return "Certificate expired!" . strval($cert_details['validTo_time_t'] - $now);
     45        // $idp_on = $days > 500;
     46    }
     47    else return "Certificate password might be wrong!";
     48}
     49
     50// check for potential problems
     51if(idp_problems(get_option( 'identity_plus_settings' )) == "renew"){
     52    $options = get_option( 'identity_plus_settings' );
     53    // if the problem is renew perform a renew and then re-initialize options
     54    idenity_plus_renew_service_agent_certificate();
     55}
     56
     57/**
     58 * Lazy create identity + API object
     59 *
     60 * @param unknown $options
     61 */
     62function identity_plus_create_api($options){
     63    return new Identity_Plus_API(base64_decode($options['cert-data']), $options['cert-password']);
     64}
     65
    2566function idp_add_user_id_column($columns) {
    2667    $columns['user_id'] = 'Id +';
     
    2869}
    2970 
     71
    3072function idp_show_user_id_column_content($value, $column_name, $user_id) {
    3173    $user = get_userdata( $user_id );
     
    3880}
    3981
     82
     83
    4084function identity_plus_initialize(){
    4185        if(!function_exists("curl_init")){
     86            error_log("Curl extension is not installed on the server! Identity + needs php5-curl extension to work. <br>(for Ubuntu type: sudo apt-get install php5-curl)");
    4287            return;
    43             add_settings_error('identity_plus_settings', 'identity-plus-curl-error', "Curl extension is not installed on the server! Identity + needs php5-curl extension to work. <br>(for Ubuntu type: sudo apt-get install php5-curl)", "error");
    44         }
     88        }
     89
     90        // attempt to start session
     91        session_start();
    4592   
    4693        // make sure we have everything that is needed to
    4794        // run Identity + (certificate, password)
    4895        $options = get_option( 'identity_plus_settings' );
    49         $idp_on = !empty($options) && isset($options['cert-file']) && file_exists($options['cert-file']) && isset($options['cert-password']);
    50 
    51         if($idp_on){
    52             $cert_store = array();
    53             $idp_on = openssl_pkcs12_read (file_get_contents($options['cert-file']) , $cert_store , $options['cert-password']);
    54         }
     96
     97        if($_GET['identity-plus-register-intent']){
     98            idenity_plus_issue_service_agent_certificate();
     99        }
    55100
    56101        // if we have Identity + then we can start using it
    57         if($idp_on){
    58             // attempt to start session
    59             session_start();
     102        if(!idp_problems($options)){
    60103            $identity_plus_api = null;
    61104
    62105            // if returning from Identity + with information payload
    63106            // extract the payload set the session variable
    64             if($_GET['resp']){
     107            if($_GET['identity-plus-intent']){
    65108                    // the response gives us a reference  (a one time anonymous id corresponding to the user)
    66109                    // will use that as anonymous id, the server does the rest
    67                     $_SESSION['identity-plus-anonymous-id'] = $_GET['resp'];
    68             }
    69 
    70             // if returning from Identity + with information payload
    71             // extract the payload set the session variable
    72             else if($_GET['idp-api-response']){
    73                     // create the API in a lazy way, only if it is necessary
    74                     if($identity_plus_api == null) $identity_plus_api = identity_plus_create_api($options);
    75                     $identity_plus_api->legacy_http_extract_anonymous_id($_SESSION);
     110                    $_SESSION['identity-plus-anonymous-id'] = $_GET['identity-plus-intent'];
    76111            }
    77112   
     
    111146            $is_resource_protected = false;
    112147            $page = $_SERVER['REQUEST_URI'];
    113             $filter = isset($options['page-filter']) && strlen($options['page-filter']) > 0 ? $options['page-filter'] : "/wp-admin\n/wp-login.php";
     148            $filter = isset($options['page-filter']) && strlen($options['page-filter']) > 0 ? $options['page-filter'] : "/wp-admin\n/wp-login.php\n/?rest_route=/\n/wp-json/";
    114149   
    115150            // iterate through the filter and see if the resource is protected
     
    147182
    148183/**
    149  * Lazy create identity + API object
    150  *
    151  * @param unknown $options
    152  */
    153 function identity_plus_create_api($options){
    154         return new Identity_Plus_API(file_get_contents($options['cert-file']), $options['cert-password']);
    155 }
    156 
    157 
    158 /**
    159184 * Issue an API call to Identity + and obtain the Certificate status and the
    160185 * Identity + Profile associated with the certificate.
     
    184209            exit();
    185210        }
    186         else $_SESSION['identity-plus-user-profile'] = $profile;
    187        
     211        else{
     212            $_SESSION['identity-plus-user-profile'] = $profile;
     213            $_SESSION['identity-plus-anonymous-id'] = $profile->authorizing_certificate;
     214        }
     215
    188216        return $identity_plus_api;
    189217}
    190218
     219/**
     220 * Facilitate auto binding of the current user
     221 */
     222function auto_bind_current_user(){
     223    // get the options again and create the api
     224    $options = get_option( 'identity_plus_settings' );
     225    if($identity_plus_api == null) $identity_plus_api = identity_plus_create_api($options);
     226   
     227    $now = time();
     228    $your_date = strtotime(wp_get_current_user()->user_registered);
     229    $days = ceil(abs($now - $your_date) / 86400);
     230    $profile = $identity_plus_api->bind_local_user($_SESSION['identity-plus-anonymous-id'], wp_get_current_user()->ID, $days);
     231   
     232    // make sure we are have a local user id bound
     233    if($profile->local_user_name != null){
     234        add_user_meta($user_id, 'identity-plus-bound', $profile->local_user_name);
     235    }
     236
     237    // update session data with fresh information after binding
     238    $_SESSION['identity-plus-user-profile'] = $profile;
     239    $_SESSION['identity-plus-anonymous-id'] = $profile->authorizing_certificate;
     240}
    191241
    192242/**
     
    204254           
    205255        // If user is logged in and the Identity + profile is not bound
     256        // we are disabling this to allow for manual connect / disconnect
    206257        if(is_user_logged_in() && !isset($profile->local_user_name) && false){
    207             if($identity_plus_api == null) $identity_plus_api = identity_plus_create_api($options);
    208    
    209             $now = time();
    210             $your_date = strtotime(wp_get_current_user()->user_registered);
    211             $days = ceil(abs($now - $your_date) / 86400);
    212             $profile = $identity_plus_api->bind_local_user($_SESSION['identity-plus-anonymous-id'], wp_get_current_user()->ID, $days);
    213             $_SESSION['identity-plus-user-profile'] = $profile;
     258            auto_bind_current_user();
    214259        }
    215260           
     
    228273            }
    229274        }
    230            
     275
     276        // Enforce is on and No Identity + Profile
     277        // we should block the access
     278        if(!is_user_logged_in() && !isset($profile->local_user_name) && isset($options['enforce']) && $options['enforce']){
     279            include 'protected.php';
     280            exit();
     281        }
     282       
    231283        // make sure we remember how this user is bound locally as well
    232284        // this is not entirely necessary, Identity + will communicate this info back,
     
    302354        if(isset($_SESSION['identity-plus-anonymous-id']) && $_SESSION['identity-plus-anonymous-id'] != 'N/A'){
    303355                $options = get_option( 'identity_plus_settings' );
    304                 if(!empty($options) && isset($options['cert-file']) && isset($options['cert-password'])){
     356                if(!empty($options) && isset($options['cert-data']) && isset($options['cert-password'])){
    305357                        $identity_plus_api = identity_plus_create_api($options);
    306358                }
     
    337389                .identity-plus-cf{border:0px; width:100%; height:110px; overflow-x:hidden; overflow-y:hidden; border-top:1px solid #000000;}
    338390                @media screen and (max-width: 700px){ .identity-plus-cf{height:210px; overflow-x:hidden; overflow-y:hidden; }}
    339                 #wpfooter{bottom:120px;
     391                #wpfooter{bottom:120px;}
     392                #wpcontent{background:#FFFFFF;}
    340393        </style>
    341         <?php
     394        <?php
     395}
     396
     397function idenity_plus_renew_service_agent_certificate(){
     398    $options = get_option( 'identity_plus_settings' );
     399    if($identity_plus_api == null) $identity_plus_api = identity_plus_create_api($options);
     400    $new_identity = $identity_plus_api->issue_service_agent_identity(null, "Default");
     401
     402    if(isset($new_identity->p12) && isset($new_identity->password)){
     403        $options['cert-data'] = $new_identity->p12;
     404        $options['cert-password'] = $new_identity->password;
     405    }
     406
     407    update_option( 'identity_plus_settings', $options);
     408}
     409
     410function idenity_plus_issue_service_agent_certificate(){
     411    $options = get_option( 'identity_plus_settings' );
     412
     413    // we remember this reference because we will fetch the user profile with it
     414    // instead of the certificate id, if we do not already have one
     415    if(!isset($_SESSION['identity-plus-anonymous-id'])) $_SESSION['identity-plus-anonymous-id'] = $_GET['identity-plus-register-intent'];
     416
     417    if($identity_plus_api == null) $identity_plus_api = identity_plus_create_api($options);
     418    $new_identity = $identity_plus_api->register_service($_GET['identity-plus-register-intent'], "Default");
     419
     420    if(isset($new_identity->p12) && isset($new_identity->password)){
     421        $options['cert-data'] = $new_identity->p12;
     422        $options['cert-password'] = $new_identity->password;
     423    }
     424
     425    update_option( 'identity_plus_settings', $options);
     426
     427    $identity_plus_api == null;
     428    unset($_SESSION['identity-plus-user-profile']);
     429
     430    auto_bind_current_user();
    342431}
    343432
     
    361450        // unbind users on Identity +
    362451        $options = get_option( 'identity_plus_settings' );
    363         if(!empty($options) && isset($options['cert-file']) && isset($options['cert-password'])){
    364                 $identity_plus_api = new Identity_Plus_API(file_get_contents($options['cert-file']), $options['cert-password']);
     452        if(!empty($options) && isset($options['cert-data']) && isset($options['cert-password'])){
     453                $identity_plus_api = new Identity_Plus_API(base64_decode($options['cert-data']), $options['cert-password']);
    365454   
    366455                $users = get_users(array('meta_key' => 'identity-plus-bound'));
  • identity-plus/trunk/lib/settings_panel.php

    r1933272 r2184906  
    77
    88use identity_plus\api\communication\Intent_Type;
     9use identity_plus\api\Identity_Plus_API;
    910
    1011
     
    1617
    1718function identity_plus_add_admin_menu(  ) {
    18         add_options_page( 'IdentityPlus Settings', 'Identity +', 'manage_options', 'identity_plus_network_of_trust', 'identity_plus_options_page' );
     19        add_options_page( 'IdentityPlus Settings', 'Identity Plus', 'manage_options', 'identity_plus_network_of_trust', 'identity_plus_options_page' );
    1920}
    2021
     
    2223
    2324function identity_plus_settings_init(  ) {
    24         if(!function_exists("curl_init")) add_settings_error('identity_plus_settings', 'identity-plus-curl-error', "Curl extension is not installed on the server! Identity + needs php5-curl extension to work. <br>(for Ubuntu type: sudo apt-get install php5-curl)", "error");
    25        
    26         $options = get_option( 'identity_plus_settings' );
    27    
    28         if(!empty($options) && isset($options['cert-file'])){
    29                 $cs = array();
    30                 if(!openssl_pkcs12_read (file_get_contents($options['cert-file']), $cs , isset($options['cert-password']) ? $options['cert-password'] : '')){
    31                         add_settings_error('identity_plus_settings', 'identity-plus-api-certificate-error', "Certificate password might be wrong!", "error");
    32                 }
     25        if(!function_exists("curl_init")){
     26            add_settings_error('identity_plus_settings', 'identity-plus-curl-error', "Curl extension is not installed on the server! Identity + needs php-curl extension to work. <br>(for Ubuntu type: sudo apt-get install php-curl)", "error");
    3327        }
    34         else add_settings_error('identity_plus_settings', 'identity-plus-api-certificate-error', "API Certificate is missing!", "error");
    35    
    36         register_setting( 'identity_plus_cert_section', 'identity_plus_settings' , 'identity_plus_handle_file_upload');
    37    
    38         add_settings_section('identity_plus_identity_plus_cert_section_section', __( 'API Certificate', 'identity_plus' ), 'identity_plus_api_section_callback', 'identity_plus_cert_section');
    39         add_settings_field('cert-file', __( 'Certificate File', 'identity_plus' ),  'identity_plus_cert_file_render', 'identity_plus_cert_section', 'identity_plus_identity_plus_cert_section_section');
    40         add_settings_field('cert-password', __( 'Certificate Password', 'identity_plus' ), 'identity_plus_cert_password_render', 'identity_plus_cert_section',  'identity_plus_identity_plus_cert_section_section' );
    41            
    42         add_settings_section('identity_plus_access_section',    __( 'Resource Access', 'identity_plus' ), 'identity_plus_settings_section_callback', 'identity_plus_cert_section');
    43         add_settings_field('enforce', __( 'Filtered Page Access', 'identity_plus' ), 'identity_plus_enforce_render', 'identity_plus_cert_section', 'identity_plus_access_section');
    44 #       add_settings_field('lock-down', __( 'Lock Down Filtered Pages', 'identity_plus' ), 'identity_plus_lock_down_render', 'identity_plus_cert_section', 'identity_plus_access_section');
    45         add_settings_field('page-filter', __( 'Page Filter', 'identity_plus' ), 'identity_plus_page_filter_render', 'identity_plus_cert_section',   'identity_plus_access_section');
    46    
    47         add_settings_section('identity_plus_network_of_trust_section', __( 'Network Of Trust', 'identity_plus' ), 'identity_plus_not_section_callback', 'identity_plus_cert_section');
    48         add_settings_field('comments', __( 'Comments', 'identity_plus' ),   'identity_plus_comments_render', 'identity_plus_cert_section', 'identity_plus_network_of_trust_section');
     28
     29        $problems = idp_problems(get_option( 'identity_plus_settings' ));
     30        if($problems) add_settings_error('identity_plus_settings', 'identity-plus-api-certificate-error', $problems, "error");
    4931}
    5032
     
    5234
    5335function identity_plus_cert_file_render( ) {
    54         $options = get_option( 'identity_plus_settings' );?>
    55         <input type="file" name="identity-plus-api-cert-file" /><?php
    56 }
    57 
     36        ?><input type="file" style="margin-top:5px;" name="identity-plus-api-cert-file" /><?php
     37}
    5838
    5939
    6040function identity_plus_cert_password_render(  ) {
    6141        $options = get_option( 'identity_plus_settings' ); ?>
    62         <input type='text' name='identity_plus_settings[cert-password]' style="width:350px;" value='<?php echo isset($options['cert-password']) ? $options['cert-password'] : ""; ?>'><?php
    63 }
    64 
     42        <input type='text' name='identity_plus_settings[cert-password]' style="width:350px; margin-bottom:10px; margin-top:5px;" placeholder="Type/Paste Certificate Password" value='<?php echo isset($options['cert-password']) ? $options['cert-password'] : ""; ?>'><?php
     43}
    6544
    6645
     
    7857function identity_plus_enforce_render(  ) {
    7958        $options = get_option( 'identity_plus_settings' );?>
    80         <input type='checkbox' id='identity_plus_settings[enforce]' name='identity_plus_settings[enforce]' <?php isset($options['enforce']) ? checked( $options['enforce'], 1 ) : ""; ?> value='1'><label for='identity_plus_settings[enforce]'>Enforce Identity + Device Certificate</label>
    81         <p class="identity-plus-hint" style="max-width:640px; font-size:90%; color:rgba(0, 0, 0, 0.6);">When Identity + certificate is enforced, resources starting with any of the enumerated filters will only
    82         be accessible from devices (desktop / laptop /mobile ) bearing a valid Identity + SSL Client Certificate. Local user roles apply</p><?php
     59        <input type='checkbox' id='identity_plus_settings[enforce]' name='identity_plus_settings[enforce]' <?php isset($options['enforce']) ? checked( $options['enforce'], 1 ) : ""; ?> value='1'><label for='identity_plus_settings[enforce]'>Enforce Device Identity</label>
     60        <p class="identity-plus-hint" style="margin-bottom:10px;">When Identity Plus device id is enforced, resources starting with any of the enumerated filters will only
     61        be accessible from devices (desktop / laptop /mobile ) bearing a valid Identity + SSL Client Certificate. </p><?php
    8362}
    8463
     
    9574function identity_plus_page_filter_render(  ) {
    9675        $options = get_option( 'identity_plus_settings' );?>
    97         <label for='identity_plus_settings[page-filter]'>One filter per line.</label>
    98         <textarea cols='40' rows='5' name='identity_plus_settings[page-filter]'><?php echo isset($options['page-filter']) && strlen($options['page-filter']) > 0 ? $options['page-filter'] : "/wp-admin\n/wp-login.php"; ?></textarea>
     76        <textarea cols='40' rows='5' name='identity_plus_settings[page-filter]'><?php echo isset($options['page-filter']) && strlen($options['page-filter']) > 0 ? $options['page-filter'] : "/wp-admin\n/wp-login.php\n/?rest_route=/\n/wp-json/"; ?></textarea>
    9977        <?php
    10078}
     
    11088
    11189
    112 
    113 function identity_plus_api_section_callback(  ) {
    114         ?><p class="identity-plus-separator" style="padding-top:5px;"></p><p class="identity-plus-hint">With Identity + all communication is encrypted, even redirects. We don't use tokens, we use public key criptography for authentication.</p>
    115         <div class="cert"><h4>Certificate Details</h4><?php
    116         $options = get_option( 'identity_plus_settings' );
    117         if(!empty($options) && isset($options['cert-file'])){
    118                 $cs = array();
    119                 if(openssl_pkcs12_read (file_get_contents($options['cert-file']), $cs , isset($options['cert-password']) ? $options['cert-password'] : '')){
    120                         $cert_details = openssl_x509_parse($cs['cert']);
    121                         $now = time();
    122                         $your_date = strtotime(wp_get_current_user()->user_registered);
    123                         $days = floor(abs($cert_details['validTo_time_t'] - $now) / 86400);
    124                         ?>
    125                         <p><span>Serial No: </span><?php echo strtoupper(dechex($cert_details['serialNumber'])) ?></p>
    126                         <p><span>Subject: </span><?php echo substr(str_replace("/", ", ", $cert_details['name']), 2) ?></p>
    127                         <p><span>Valid Until: </span><?php echo date(DATE_RFC2822, $cert_details['validTo_time_t']) ?></p>
    128                         <p><span>Expires In: </span><?php echo  $days?> days</p>
    129                         <?php
    130                 }
    131                 else{
    132                         ?><p>API certificate cannot be read.</p><?php
    133                 }
    134         }
    135         ?><p style="margin:10px 0 0 0; float:left; clear:both; font-size:80%; max-width:550px; color:#808080;">file: <?php echo !isset($options['cert-file']) ? "API Certificate Not Loaded" : $options['cert-file']; ?> <a target="_blank" href="https://my.identity.plus"><?php echo !isset($options['cert-file']) ? "Get A Certificate" : "Renew Certificate"; ?></a></p></div><?php
    136 }
    137 
    138 
    139 
    14090function identity_plus_settings_section_callback(  ) {
    14191        ?><p class="identity-plus-separator" style="padding-top:5px;"></p><p class="identity-plus-hint">You can restrict access to critical sections of your site to authorized devices only</p><?php
     
    14797        ?>
    14898        <style>
    149                 .identity-plus-main-fm {margin:0; background:url('<?php echo plugins_url( 'img/idp.svg', __FILE__ ) ?>') no-repeat top left; background-size:64px;}
     99                .identity-plus-main-fm{ float:left; overflow:hidden; clear:left;}
     100                .identity-plus-main-fm-header {margin:0; background:url('<?php echo plugins_url( 'img/idp.svg', __FILE__ ) ?>') no-repeat top left; background-size:42px; margin-bottom:30px;}
     101                .identity-plus-main-fm-header h1{padding-left:50px; padding-top:20px; margin-bottom:0; font-size:30px;font-weight:normal; }
     102                .identity-plus-main-fm-header h5{padding-left:50px; font-size:14px; font-weight:300; padding-bottom:0px; padding-top:0; margin:10px 0px 0px 0px;}
     103                h5.identity-plus-title {font-weight:300; font-size:16px; line-height:130%; margin:0; max-width:640px; color:#909090;}
     104                .identity-plus-main-fm p{margin:0;}
    150105                .identity-plus-main-fm th{padding-bottom:15px; padding-top:15px; color:#136a92;}
    151106                .identity-plus-main-fm td{padding-bottom:10px; padding-top:10px; }
    152                 .identity-plus-main-fm h1{padding-left:80px; padding-top:10px; margin-bottom:0; font-size:36px;font-weight:normal; }
    153                 .identity-plus-main-fm h5{padding-left:80px; font-size:20px; font-weight:300; padding-bottom:5px; padding-top:0; margin-top:15px;}
    154                 .identity-plus-main-fm h2, .identity-plus-main-fm h3{border-bottom:0; background:#303030; float:left; clear:left; padding:5px 20px; margin-bottom:0px; color:#62B2F3; font-weight:normal; border-top-left-radius:5px; border-top-right-radius:5px; margin-left:10px;}
    155                 .identity-plus-main-fm h4{border-bottom:1px solid #E0E0E0; color:#707070; padding-bottom:3px; padding-top:10px; margin-bottom:5px; font-weight:normal; font-size:16px;padding-top:0; margin-top:0; }
     107                .identity-plus-main-fm h2, .identity-plus-main-fm h3{border:1px solid #72777c; border-bottom:0; background:#72777c; float:left; clear:left; padding:8px 20px; margin-bottom:0px; color:#FFFFFF; font-weight:normal; border-top-left-radius:1px; border-top-right-radius:1px; margin-left:0px; margin-top:50px;}
     108                .identity-plus-main-fm h4{border-bottom:1px solid #E0E0E0; color:#707070; padding-bottom:3px; padding-top:15px; margin-bottom:5px; font-weight:normal; font-size:16px;padding-top:0; margin-top:0; }
    156109                .identity-plus-main-fm .cert {max-width:600px; border-radius:3px; float:left; clear:both;}
    157110                .identity-plus-main-fm .cert p span{font-weight:bold;}
    158111                .identity-plus-main-fm .cert p{margin:0px; float:left; clear:left;}
    159112                .identity-plus-main-fm .cert {padding:10px; background:rgba(255, 255, 255, 0.6); border:1px solid rgba(0, 0, 0, 0.3);}
    160                 .identity-plus-separator{border-top:1px solid #303030; margin-top:0px; float:left; width:90%; clear:both; height:5px; margin-bottom:0px;}
    161                 .identity-plus-hint{float:left; clear:both; max-width:600px; color:#606060; font-size:14px; margin-top:0px; margin-bottom:10px;}
    162                 .identity-plus-brand span{color:#4292D3;}
     113                .identity-plus-separator{border-top:1px solid #72777c; margin-top:0px; float:left; width:100%; clear:both; height:5px; margin-bottom:0px;}
     114                .identity-plus-hint{float:left; clear:both; max-width:600px; color:#909090; font-size:12px; margin-top:0px; margin-bottom:10px;}
     115                .identity-plus-brand span{color:#4292D3; margin-left:0.1em;}
    163116                .identity-plus-main-fm input, .identity-plus-main-fm textarea{ float:left; clear:left;}
    164117                .identity-plus-main-fm input[type="checkbox"]{ margin-top:0; margin-right:5px;}
     
    167120                .identity-plus-main-fm table{max-width:600px; float:left; clear:left;}
    168121                .identity-plus-main-fm table th img{border-radius:60px; border:3px solid #D0D0D0;}
     122                .identity-plus-main-fm a.toggle-off {font-size:16px; color:#202020; padding:5px 0px 5px 0px; margin-right:30px; cursor:pointer;}
     123                .identity-plus-main-fm a.toggle-on {font-size:16px; color:#202020;  padding:5px 0px 5px 0px; margin-right:30px; cursor:pointer; border-bottom:1px solid #606060; display:inline-block;}
     124                .circular_progress {transform: rotate(90deg);display: inline;}
     125                div.holder-more {overflow: hidden;width: 128px;height: 128px;margin-top: 1px;margin-right: 30px;text-align: center; padding-left: 0; display: inline-block; float:left; clear:left; margin-right:30px;}
     126                div.holder-more p.overlay {position: relative;width: 100%;line-height: 120%;top: -93px;font-weight: 400; font-size:120%;}
     127                div.holder-more p.overlay span {font-weight: 300;font-size: 90%;color: #606060;}
     128                #wpfooter{position:static;}
     129                .nodisp{display:none;}
     130                .identity-plus-main-fm input[type=checkbox], .identity-plus-main-fm input[type=radio]{margin:0px 10px 5px 0px; float;left; clear:left; box-shadow:none;}
     131                .identity-plus-main-fm input[type=text]{padding:5px; box-shadow:none;}
     132                .identity-plus-main-fm textarea{margin:0px 10px 5px 0px; float:left; clear:left; margin-bottom:20px; border-radius:1px; border:1px solid #72777c; box-shadow:none; padding:5px 10px; background:rgba(0,0,0,0.05); font-family:monospace;}
     133                .identity-plus-main-fm textarea:focus{box-shadow:none;}
     134                .identity-plus-main-fm .submit{float:left; clear:left; margin-top:0px; padding:0px; height:32px;}
     135                .identity-plus-main-fm .submit input[type="submit"]{text-decoration:none; background:#4292D3; color:#FFFFFF; display:inline-block; border-radius:1px; border:1px solid rgba(0,0,0,0.1); cursor:pointer; box-shadow:none; text-shadow:none; font-size:14px; padding:3px 18px; height:auto;}
     136                .identity-plus-main-fm a.submit{text-decoration:none; background:#4292D3; color:#FFFFFF; display:inline-block; border-radius:1px; border:1px solid rgba(0,0,0,0.1); cursor:pointer; box-shadow:none; text-shadow:none; font-size:14px; padding:8px 18px 6px 18px; height:auto;}
     137                .wp-core-ui .notice.is-dismissible{margin-left:0;}
    169138        </style>
    170139        <?php
    171140}
    172141
     142function settings_header(){ ?>
     143    <table><tr>
     144            <td><h5 class="identity-plus-title">
     145                Authenticate with your device and prevent unknown and malicious devices from accessing your Wordpress account. Great security at great convenience.
     146            </h5></td>
     147    </tr></table>
     148<?php }
     149
     150function identity_plus_api_section_callback(  ) {
     151    $problems = idp_problems(get_option( 'identity_plus_settings' ));
     152
     153    settings_header();
     154
     155    ?>
     156   
     157    <div class="identity-plus-main-fm" >
     158        <h2>Service Identity</h2>
     159        <p class="identity-plus-separator" style="padding-top:5px;"></p>
     160        <p class="identity-plus-hint">Your Worpress uses PKI credentials to authenticate into Indentity Plus. This is necessary to make sure nobody impersonates your service.</p>
     161    </div>
     162    <div class="identity-plus-main-fm" >
     163    <table class=""><tr>
     164
     165    <?php
     166   
     167    if(!$problems){
     168        // display dial for certificate lifetime
     169        // and expiry
     170        ?>
     171        <td valign="top"><div class="holder-more"><?php
     172            $perimeter = 2*3.14*60;
     173            $options = get_option( 'identity_plus_settings' );
     174            $dash = 0;
     175            $days = 0;
     176            if(!empty($options) && isset($options['cert-data'])){
     177                    $cs = array();
     178                    if(openssl_pkcs12_read (base64_decode($options['cert-data']), $cs , isset($options['cert-password']) ? $options['cert-password'] : '')){
     179                            $cert_details = openssl_x509_parse($cs['cert']);
     180                            $now = time();
     181                            $days = floor(abs($cert_details['validTo_time_t'] - $now) / 86400);
     182                            $all_days = floor(abs($cert_details['validTo_time_t'] - $cert_details['validFrom_time_t']) / 86400);
     183                            $dash = $perimeter*($days*1.0/$all_days*1.0);
     184                    }
     185            }
     186            ?><div class="holder-more">
     187            <svg width="124.0" height="124.0" viewBox="0 0 124.0 124.0" class="circular_progress">
     188                <circle cx="62.0" cy="62.0" r="60.0" fill="none" stroke="#E7E7E7" stroke-width="1.5"></circle>
     189                <circle cx="62.0" cy="62.0" r="60.0" fill="none" stroke="#007aD0" stroke-width="1.5" stroke-dasharray="<?php echo $perimeter; ?>" stroke-dashoffset="<?php echo ($perimeter - $dash);?>"></circle>
     190            </svg>
     191            <p class="overlay"><span><?php echo $days == 0 ? "" : "Expires"; ?><br><?php echo $days == 0 ? "N/A" : date("yy, M, d", $cert_details['validTo_time_t']) ?></span><br><?php echo $days == 0 ? "" : $days . "d"?><span></span></p>
     192        </div><?php
     193        ?></div>
     194        </td>
     195    <?php } ?>
     196
     197    <td valign="top"><div class="identity-plus-main-fm">
     198        <script>
     199            function toggle_renewal(mode){
     200                document.getElementById('renew-fm').className = mode == 0 ? 'identity-plus-hint' : 'nodisp';
     201                document.getElementById('upload-fm').className = mode == 0 ? 'nodisp' : 'identity-plus-hint';
     202                document.getElementById('integrated').className = mode == 0 ? 'toggle-on' : 'toggle-off';
     203                document.getElementById('manual').className = mode == 0 ? 'toggle-off' : 'toggle-on';
     204            }
     205        </script>
     206        <a id="integrated" class="toggle-on" onclick="toggle_renewal(0)">Automated</a>
     207        <a id="manual" class="toggle-off" onclick="toggle_renewal(1);">Manual</a>
     208    </div>
     209
     210    <?php if(empty($options) || !isset($options['cert-data'])){ ?>
     211        <form id="renew-fm" class="identity-plus-main-fm" action="admin-post.php" method='post' enctype="multipart/form-data">
     212                <div>
     213                    <p class="identity-plus-hint" style="font-size:13px; margin-bottom:5px;">Click the button below to add certify your ownership of this Wordpress instance.</p>
     214                    <a class="submit" href="<?php echo("https://register." . Identity_Plus_API::HOME . "/?service=" . get_bloginfo('name') . "&url=" . urlencode((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"));?>" target="_blank">Certify Ownership</a>
     215                </div>
     216        </form>
     217    <?php } else { ?>
     218        <form id="renew-fm" class="identity-plus-main-fm" action="admin-post.php" method='post' enctype="multipart/form-data">
     219                <input type="hidden" name="action" value="renew_certificate">
     220                <div>
     221                    <p class="identity-plus-hint" style="font-size:13px; margin-bottom:5px;">To avoid outage, your service identity (certificate) will be renewed automatically in <?php echo floor($days - $all_days/3); ?> days.</p>
     222                    <?php submit_button("Auto-Renew Now"); ?>
     223                </div>
     224        </form>
     225    <?php } ?>
     226
     227    <form id="upload-fm" class="nodisp" action="admin-post.php" method='post' enctype="multipart/form-data">
     228            <input type="hidden" name="action" value="upload_certificate">
     229            <div>
     230                <p class="identity-plus-hint" style="font-size:13px;">Create the service in your <a href="https://my.identity.plus" target="_blank">identityp.plus dashboard</a>, issue the Service Agent Identity and upload it manually.</p>
     231                <?php identity_plus_cert_file_render(); ?>
     232                <?php identity_plus_cert_password_render(); ?>
     233                <?php submit_button("Upload Manually"); ?>
     234            </div>
     235    </form>
     236    </td></tr></table>
     237
     238    <?php if(!$problems){
     239        // add the access restriction configuration section
     240        // and also the network of trust enrollment
     241        ?>
     242        <div class="identity-plus-main-fm" >
     243            <h2>Access Restrictions</h2>
     244            <p class="identity-plus-separator" style="padding-top:5px;"></p><p class="identity-plus-hint">You can restrict access to critical sections of your site to authorized devices only. Add one resource pattern per line.</p>
     245        </div>
     246        <form id="upload-fm" class="identity-plus-main-fm" action="admin-post.php" method='post' enctype="multipart/form-data">
     247                <input type="hidden" name="action" value="save_access">
     248                <div>
     249                    <?php identity_plus_page_filter_render(); ?>
     250                    <?php identity_plus_enforce_render(); ?>
     251                    <?php submit_button("Save"); ?>
     252                </div>
     253        </form>
     254
     255        <div class="identity-plus-main-fm" >
     256            <h2>Network of Trust</h2>
     257            <p class="identity-plus-separator" style="padding-top:5px;"></p><p class="identity-plus-hint">Collaborate with the Identity Plus community to better identify legitimate users using anonymized hooks (no personal information is shared). This will help eliminate SPAM and fake accounts.</p>
     258        </div>
     259        <form id="upload-fm" class="identity-plus-main-fm" action="admin-post.php" method='post' enctype="multipart/form-data">
     260                <input type="hidden" name="action" value="not_enroll">
     261                <div>
     262                    <?php submit_button(isset($options['not_enroll']) && $options['not_enroll'] == 1 ? "Disable" : "Enroll"); ?>
     263                </div>
     264        </form>
     265    <?php
     266    }
     267}
     268
     269add_action( 'admin_post_not_enroll', 'identity_plus_admin_not_enroll');
     270function identity_plus_admin_not_enroll(){
     271    $options = get_option( 'identity_plus_settings');
     272
     273    if(isset($options['not_enroll']) && $options['not_enroll'] == 1) $options['not_enroll'] = 0;
     274    else  $options['not_enroll'] = 1;
     275
     276    update_option( 'identity_plus_settings', $options);
     277
     278    wp_redirect( $_SERVER["HTTP_REFERER"], 302, 'WordPress' );
     279    exit;
     280    status_header(200);
     281    die("Certificate uploaded.");
     282}
     283
     284add_action( 'admin_post_save_access', 'identity_plus_admin_save_access');
     285function identity_plus_admin_save_access(){
     286    $options = get_option( 'identity_plus_settings');
     287
     288    $options['page-filter'] = $_POST["identity_plus_settings"]["page-filter"];
     289    $options['enforce'] = $_POST["identity_plus_settings"]["enforce"];
     290
     291    update_option( 'identity_plus_settings', $options);
     292
     293    wp_redirect( $_SERVER["HTTP_REFERER"], 302, 'WordPress' );
     294    exit;
     295    status_header(200);
     296    die("Certificate uploaded.");
     297}
    173298
    174299
    175300function identity_plus_options_page(  ) {
    176301        ?>
    177         <form class="identity-plus-main-fm" action='options.php' method='post' enctype="multipart/form-data">
    178                 <h1 class="identity-plus-brand">Identity<span>plus</span></h1>
    179                 <h5>man &amp; machine</h5>
    180                 <?php
    181                         settings_fields( 'identity_plus_cert_section' );
    182                         do_settings_sections( 'identity_plus_cert_section' );
    183                         submit_button();
    184                 ?>
    185         </form>
    186         <?php
    187 }
    188 
    189 
    190 
    191 function identity_plus_handle_file_upload($option){
    192         if(!empty($_FILES["identity-plus-api-cert-file"]["tmp_name"])){
    193                 $urls = wp_handle_upload($_FILES["identity-plus-api-cert-file"], array('test_form' => FALSE));
    194                 if(!empty($urls["error"])){
    195                     add_settings_error('identity_plus_settings', 'identity-plus-upload-error', $urls["error"], "error");
    196                 }
    197                 if(!empty($urls["file"])) $option['cert-file'] = $urls["file"];
    198         }
     302        <div class="identity-plus-main-fm-header">
     303            <h1 class="identity-plus-brand">identity<span>plus</span></h1>
     304            <h5>authenticate everything</h5>
     305        </div>
    199306       
    200         $old_options = get_option( 'identity_plus_settings' );
    201         if(!isset($option['cert-file']) && isset($old_options['cert-file'])) $option['cert-file'] = $old_options['cert-file'];
    202    
    203         return $option;
     307        <?php
     308       
     309        identity_plus_api_section_callback();
    204310}
    205311
     
    212318}
    213319
     320add_action( 'admin_post_upload_certificate', 'identity_plus_admin_upload_certificate');
     321function identity_plus_admin_upload_certificate(){
     322    $options = get_option( 'identity_plus_settings');
     323
     324    if(!empty($_FILES["identity-plus-api-cert-file"]["tmp_name"])){
     325        $options['cert-data'] = base64_encode(file_get_contents($_FILES["identity-plus-api-cert-file"]["tmp_name"]));
     326        $options['cert-password'] = $_POST["identity_plus_settings"]["cert-password"];
     327    }
     328
     329    update_option( 'identity_plus_settings', $options);
     330
     331    wp_redirect( $_SERVER["HTTP_REFERER"], 302, 'WordPress' );
     332    exit;
     333    status_header(200);
     334    die("Certificate uploaded.");
     335}
     336
     337add_action( 'admin_post_renew_certificate', 'identity_plus_admin_renew_certificate');
     338function identity_plus_admin_renew_certificate(){
     339    idenity_plus_renew_service_agent_certificate();
     340
     341    wp_redirect( $_SERVER["HTTP_REFERER"], 302, 'WordPress' );
     342    exit;
     343    status_header(200);
     344    die("Certificate renewed.");
     345}
    214346
    215347
     
    222354        if($identity_plus_api == null) $identity_plus_api = identity_plus_create_api($options);
    223355
    224         if(isset($_SESSION['identity-plus-user-profile'])){
    225             $profile = $identity_plus_api->bind_local_user($_SESSION['identity-plus-anonymous-id'], $user_id, $days);
    226 
    227             $_SESSION['identity-plus-user-profile'] = $profile;
    228             add_user_meta($user_id, 'identity-plus-bound', $user_id);
    229             $error = "I: Your wordpress account and your identity plus account have been connected!";
    230             set_transient("identity_plus_acc_{$user_id}", $error, 45);     
    231 
    232             wp_redirect( $_SERVER['HTTP_REFERER'] );
    233         }
    234         else{
    235             $user_info = get_userdata($user_id);
    236             $intent = $identity_plus_api->create_intent(Intent_Type::bind, $user_id, $user_info->user_firstname . ' ' . $user_info->user_lastname, $user_info->user_email, '', $_SERVER['HTTP_REFERER'] . '&bind=true');
    237             wp_redirect('https://get.identity.plus?intent=' . $intent->value);
    238         }
     356        $user_info = get_userdata($user_id);
     357        $intent = $identity_plus_api->create_intent(Intent_Type::bind, $user_id, $user_info->user_firstname . ' ' . $user_info->user_lastname, $user_info->user_email, '', $_SERVER['HTTP_REFERER'] . '&bind=true');
     358        unset($_SESSION['identity-plus-user-profile']);
     359        unset($_SESSION['identity-plus-anonymous-id']);
     360        wp_redirect(Identity_Plus_API::validation_endpoint.'/' . $intent->value);
    239361
    240362        exit();
     
    271393function identity_plus_add_idp_page(  ) {
    272394        $options = get_option( 'identity_plus_settings' );
    273         if(!empty($options) && isset($options['cert-file'])){
     395        if(!empty($options) && isset($options['cert-data'])){
    274396            add_menu_page(
    275397                    'My IdentityPlus',
    276                     'Device Identity',
     398                    'Device Login',
    277399                    'exist',
    278400                    'identity_plus_authentication',
    279401                    'identity_plus_authentication_page',
    280                     'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIgICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgICB4bWxuczpzb2RpcG9kaT0iaHR0cDovL3NvZGlwb2RpLnNvdXJjZWZvcmdlLm5ldC9EVEQvc29kaXBvZGktMC5kdGQiICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiICAgdmVyc2lvbj0iMS4xIiAgIGlkPSJMYXllcl8xIiAgIHg9IjBweCIgICB5PSIwcHgiICAgd2lkdGg9IjEyOHB4IiAgIGhlaWdodD0iMTI4cHgiICAgdmlld0JveD0iMCAwIDEyOCAxMjgiICAgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMTI4IDEyODsiICAgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgICBpbmtzY2FwZTp2ZXJzaW9uPSIwLjkxIHIxMzcyNSIgICBzb2RpcG9kaTpkb2NuYW1lPSJkYXJrLXBsdXMtc2ltcGxlLnN2ZyI+PG1ldGFkYXRhICAgICBpZD0ibWV0YWRhdGEzOSI+PHJkZjpSREY+PGNjOldvcmsgICAgICAgICByZGY6YWJvdXQ9IiI+PGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+PGRjOnR5cGUgICAgICAgICAgIHJkZjpyZXNvdXJjZT0iaHR0cDovL3B1cmwub3JnL2RjL2RjbWl0eXBlL1N0aWxsSW1hZ2UiIC8+PC9jYzpXb3JrPjwvcmRmOlJERj48L21ldGFkYXRhPjxkZWZzICAgICBpZD0iZGVmczM3IiAvPjxzb2RpcG9kaTpuYW1lZHZpZXcgICAgIHBhZ2Vjb2xvcj0iI2ZmZmZmZiIgICAgIGJvcmRlcmNvbG9yPSIjNjY2NjY2IiAgICAgYm9yZGVyb3BhY2l0eT0iMSIgICAgIG9iamVjdHRvbGVyYW5jZT0iMTAiICAgICBncmlkdG9sZXJhbmNlPSIxMCIgICAgIGd1aWRldG9sZXJhbmNlPSIxMCIgICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwIiAgICAgaW5rc2NhcGU6cGFnZXNoYWRvdz0iMiIgICAgIGlua3NjYXBlOndpbmRvdy13aWR0aD0iOTQ4IiAgICAgaW5rc2NhcGU6d2luZG93LWhlaWdodD0iNDgwIiAgICAgaWQ9Im5hbWVkdmlldzM1IiAgICAgc2hvd2dyaWQ9ImZhbHNlIiAgICAgaW5rc2NhcGU6em9vbT0iMS40ODk3NjUxIiAgICAgaW5rc2NhcGU6Y3g9IjEwNi45NzU5IiAgICAgaW5rc2NhcGU6Y3k9IjY0IiAgICAgaW5rc2NhcGU6d2luZG93LXg9IjEzMSIgICAgIGlua3NjYXBlOndpbmRvdy15PSI0NDAiICAgICBpbmtzY2FwZTp3aW5kb3ctbWF4aW1pemVkPSIwIiAgICAgaW5rc2NhcGU6Y3VycmVudC1sYXllcj0iZzMiIC8+PGcgICAgIGlkPSJnMyIgICAgIHN0eWxlPSJmaWxsOiNjY2NjY2MiPjxwYXRoICAgICAgIHN0eWxlPSJmaWxsOiNjY2NjY2MiICAgICAgIGQ9Im0gMCwwIDAsMTI4IDEyOCwwIDAsLTEyOCB6IG0gMTIuNjQwNjI1LDQwLjAxNzU3OCAxMS43MzYzMjgsMCAwLDkuNTcyMjY2IC0xMS43MzYzMjgsMCB6IG0gNDQuMDY0NDUzLC02IDExLjgwMjczNCwwIDAsNTcuMDE1NjI1IGMgLTguMDAxNzcsLTAuMzY2MTE5IC0xMi41Nzk4MTgsMC4zMjQzMTMgLTIzLjkwMDM5LDAuOTQ5MjE5IC00LjUyNDU0NSwwIC04LjI0MTM2MywtMS43OTIyOSAtMTEuMTQ4NDM4LC01LjM3Njk1MyAtMi45MDcwNzQsLTMuNjA2NTIyIC00LjM1OTM3NSwtOC4yMzkyNDYgLTQuMzU5Mzc1LC0xMy45MDAzOTEgMCwtNS42NjExNDUgMS40NTIzMDEsLTEwLjI4NDQ3OCA0LjM1OTM3NSwtMTMuODY5MTQgMi45MDcwNzUsLTMuNjA2NTIyIDYuNjIzODkzLC01LjQxMDE1NyAxMS4xNDg0MzgsLTUuNDEwMTU3IDE3LjE0MDM1NywxLjA2OTY5IDExLjA2MDU2NCw0LjM5NDExNCAxMi4wOTc2NTYsLTE5LjQwODIwMyB6IG0gMzUuNzM2MzI4LDE0LjkxNzk2OSA3LjgwNDY4NCwwIDAsMTcuMTc5Njg3IDE3LjExMzI5LDAgMCw3LjczNjMyOCAtMTcuMTEzMjksMCAwLDE3LjE4MTY0MSAtNy44MDQ2ODQsMCAwLC0xNy4xODE2NDEgLTE3LjExMzI4MSwwIDAsLTcuNzM2MzI4IDE3LjExMzI4MSwwIHogbSAtNzkuODAwNzgxLDUuMzc2OTUzIDExLjczNjMyOCwwIDAsMzYuNzIwNzAzIC0xMS43MzYzMjgsMCB6IG0gMzYuMzI2MTcyLDcuNjM4NjcyIGMgLTIuNDkxNzc4LDAgLTQuNDAzMDA4LDAuOTE3ODU5IC01LjczNjMyOCwyLjc1MzkwNiAtMS4zMTE0NjIsMS44MzYwNDcgLTEuOTY4NzUsNC41MDI3NjcgLTEuOTY4NzUsOCAwLDMuNDk3MjMzIDAuNjU3Mjg4LDYuMTYzOTUzIDEuOTY4NzUsOCAxLjMzMzMyLDEuODM2MDQ3IDMuMjQ0NTUsMi43NTM5MDYgNS43MzYzMjgsMi43NTM5MDYgMi41MTM2MzYsMCA0LjQyNjgxOSwtMC45MTc4NTkgNS43MzgyODEsLTIuNzUzOTA2IDEuMzMzMzIsLTEuODM2MDQ3IDIsLTQuNTAyNzY3IDIsLTggMCwtMy40OTcyMzMgLTAuNjY2NjgsLTYuMTYzOTUzIC0yLC04IC0xLjMxMTQ2MiwtMS44MzYwNDcgLTMuMjI0NjQ1LC0yLjc1MzkwNiAtNS43MzgyODEsLTIuNzUzOTA2IHoiICAgICAgIGlkPSJyZWN0NSIgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIgICAgICAgc29kaXBvZGk6bm9kZXR5cGVzPSJjY2NjY2NjY2NjY2NjY2NzY2NjY2NjY2NjY2NjY2NjY2NjY2Njc2NzY3Njc2NzIiAvPjwvZz48ZyAgICAgaWQ9ImcyNSIgLz48ZyAgICAgaWQ9ImcyNyIgLz48ZyAgICAgaWQ9ImcyOSIgLz48ZyAgICAgaWQ9ImczMSIgLz48ZyAgICAgaWQ9ImczMyIgLz48L3N2Zz4='
     402                    'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJMYXllcl8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIKCSB3aWR0aD0iNjQwcHgiIGhlaWdodD0iNjQwcHgiIHZpZXdCb3g9IjAgMCA2NDAgNjQwIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA2NDAgNjQwIiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPGc+PHBhdGggZmlsbD0iIzQ1OTZDRSIgZD0iTTI0NC44NTcsNTg4LjAyN0gxMDcuODMxTDM5NS41MTMsMy40MmgxMzYuNjU2TDI0NC44NTcsNTg4LjAyN3oiLz48L2c+Cjwvc3ZnPgo='
    281403            );
    282404        }
    283405}
     406
     407function connect_header(){ ?>
     408    <table><tr>
     409            <th><img width="64" height="64" src="<?php echo plugins_url( 'img/unknown.jpg', __FILE__ ) ?>"></th>
     410            <td><p class="identity-plus-hint">
     411                Your Wordpress uses <a target="_blank" title="My Identity Plus Application" href="https://my.identity.plus"class="identity-plus-brand">identity<span>plus</span></a> to protect your account and your credentials.
     412                You can now enjoy secure, passwordless authentication experience. Only devices owned and registered by you can access your Wordpress account.
     413            </p></td>
     414    </tr></table>
     415<?php }
    284416
    285417function identity_plus_idp_page(  ) {
     
    295427
    296428        ?>
    297                 <?php if(get_user_meta($user_id, 'identity-plus-bound', true)){ ?>
    298                     <table><tr>
    299                             <th><img width="64" height="64" src="https://get.identity.plus/widgets/profile-picture"></th>
    300                             <td><p class="identity-plus-hint">
    301                                 Your Wordpress uses <a target="_blank" title="My Identity Plus Application" href="https://my.identity.plus"><span>identity</span></a> to protect your account and your credentials.
    302                                 You can now enjoy secure password-less experience. Only devices owned and registered by you can access your Wordpress account.
    303                             </p></td>
    304                     </tr></table>
     429                <?php if(get_user_meta($user_id, 'identity-plus-bound', true)){
     430                    connect_header();
     431
     432                    ?>
    305433
    306434                    <h2>Disconnect</h2><p class="identity-plus-separator" style="padding-top:5px;"></p>
    307                     <?php if(isset($options['enforce']) && checked( $options['enforce'], 1 )){ ?>
     435                    <?php if(isset($options['enforce']) && $options['enforce'] == 1 ){ ?>
    308436                        <p class="identity-plus-hint" >Your <a href="<?php echo admin_url('options-general.php?page=identity_plus_network_of_trust'); ?>">identityplus settings</a> only allow admin access from certified devices. Disconnect is disabled as you would lock yourself out from admin section.</p>
    309437                    <?php } else { ?>
    310438                        <p class="identity-plus-hint" >By disconnecting your identityplus account from the local account, you will lose the ability to sign in via device id. Are you sure?</p>
    311439                        <input type="hidden" name="action" value="identity_plus_disconnect">
    312                         <div><input type="checkbox" id="idp-i-am-sure" name="idp-i-am-sure" onchange="document.getElementById('identity_plus_disconnect').style.display = document.getElementById('idp-i-am-sure').checked ? 'block' : 'none';"><label for="idp-i-am-sure">Yes, I am sure I want to disconnect.</label></div>
    313                         <input type="submit" id="identity_plus_disconnect" style="display:none; background:#900000; color:#FFFFFF; padding:7px 15px 5px 15px; border-radius:2px; border:1px solid #500000" value="DISCONNECT">
     440                        <div style="margin-top:10px;"><input type="checkbox" id="idp-i-am-sure" name="idp-i-am-sure" onchange="document.getElementById('identity_plus_disconnect').style.display = document.getElementById('idp-i-am-sure').checked ? 'block' : 'none';"><label for="idp-i-am-sure">Yes, I am sure I want to disconnect.</label></div>
     441                        <input type="submit" id="identity_plus_disconnect" style="display:none; background:#900000; color:#FFFFFF; padding:8px 18px 6px 18px; border-radius:3px; border:1px solid rgba(0,0,0,0.1);" value="Disconnect">
    314442                    <?php } ?>
    315443
    316                 <?php } else if(isset($_SESSION['identity-plus-user-profile'])){ ?>
    317                     <table><tr>
    318                             <th><img width="64" height="64" src="https://get.identity.plus/widgets/profile-picture"></th>
    319                             <td>
    320                                 <p class="identity-plus-hint">
    321                                     Your Wordpress uses <a target="_blank" title="My Identity Plus Application" href="https://identity.plus"><span>identity</span></a> to protect your account and your credentials by
    322                                     only allowing devices owned and registered by you to access your Wordpress account.
    323                                 </p>
    324                             </td>
    325                     </tr></table>
     444                <?php } else if(isset($_SESSION['identity-plus-user-profile'])){
     445                    connect_header();
     446
     447                    ?>
    326448                   
    327449                    <p class="identity-plus-hint" >Connect your identity<span class="identity-plus-brand">plus</span> account for secure, password-less login experience.</p>
    328450                    <input type="hidden" name="action" value="identity_plus_connect">
    329                     <input type="submit" id="identity_plus_disconnect" style="background:#303030; color:#62B2F3; padding:7px 15px 5px 15px; border-radius:2px; border:1px solid #000000" value="CONNECT">
    330                 <?php } else { ?>
    331                     <table><tr>
    332                             <td>
    333                                 <p class="identity-plus-hint">
    334                                     Your Wordpress uses <a target="_blank" title="My Identity Plus Application" href="https://identity.plus"><span>identity</span></a> to protect your account and your credentials by
    335                                     only allowing devices owned and registered by you to access your Wordpress account.
    336                                 </p>
    337                             </td>
    338                     </tr></table>
     451                    <input type="submit" id="identity_plus_disconnect" style="background:#4292D3; color:#FFFFFF; padding:8px 18px 6px 18px; border-radius:3px; border:1px solid rgba(0,0,0,0.1); cursor:pointer; margin-top:10px;" value="Connect">
     452                <?php } else {
     453                    connect_header();
     454
     455                    ?>
    339456                   
    340                     <p class="identity-plus-hint" >Get your free <span class="identity-plus-brand">plus</span> account for secure, password-less login experience.</p>
     457                    <p class="identity-plus-hint" >Get your free identity<span class="identity-plus-brand">plus</span> account for secure, password-less login experience.</p>
    341458                    <input type="hidden" name="action" value="identity_plus_connect">
    342459                    <input type="submit" id="identity_plus_disconnect" style="background:#303030; color:#62B2F3; padding:7px 15px 5px 15px; border-radius:2px; border:1px solid #000000" value="Get Id+">
     
    348465function identity_plus_authentication_page(  ) {
    349466        ?>
     467        <div class="identity-plus-main-fm-header">
     468            <h1 class="identity-plus-brand">identity<span>plus</span></h1>
     469            <h5>authenticate everything</h5>
     470        </div>
    350471        <form class="identity-plus-main-fm" method="post" action="<?php echo admin_url( 'admin.php' ); ?>">
    351                 <h1 class="identity-plus-brand">Identity<span>plus</span></h1>
    352                 <h5>man &amp; machine</h5>
    353472                <?php wp_nonce_field('my_delete_action'); ?>
    354473                <?php identity_plus_idp_page(); ?>
     
    359478
    360479add_filter('upload_mimes', 'identity_plus_enable_extra_extensions');
    361 
  • identity-plus/trunk/readme.txt

    r2032170 r2184906  
    33Tags: authentication, security, 2factor, comments, spam, VPN, tls authentication, SSL client certificate, device identity, identity in the browser, two factor, login, two step authentication, password, admin, mobile, multi-factor, android, iphone, sso, strong two-step verification
    44Requires at least: 3.9
    5 Tested up to: 4.9.8
    6 Stable tag: 1.0
     5Tested up to: 5.2.4
     6Stable tag: 2.0
    77License: GPLv2 or later
    88License URI: http://www.gnu.org/licenses/gpl-2.0.html
     
    78781. If the certificate in your browser expires, or you manually revoke it you will not be able to access your blog. This conflict needs to be resolved on Identityplus. Simply issue a new certificate for your browser, install it and all will be back to normal.
    79792. You lose your device and it's connected to your Identityplus. Take your other device, go to Identityplus and revoke the certificate of your lost device. This will revoke access to any Identityplus bound account, so you are safe.
    80 3. You locked your self out of your Wordpress. No problem. You need to go to your Worpress back-end, (access the files). In your wp-content/uploads/.../, you will find the certificate file you uploaded (a *.p12 keystore file). Delete the file. This will disable the plugin, and you can use your regular wordpress login to access your back-end.
     803. You locked your self out of your Wordpress. No problem.
     81
     82    a. You need to go to your Worpress back-end, (access the files).
     83    b. In your wp-content/plugins/identity-plus/lib folder, edit the initialize.php file.
     84    c. Uncomment this line: // if(True) return "Manually disabled ...";
     85    d. Access your Wordpress using user name and password
     86    e. Uninstall the plugin and perform a fresh install
    8187
    8288== Changelog ==
     89
     90== 2.0 ==
     91This is a major update. We recommend deactivating the "Enforce Identity + Device Certificate" flag for safety during certificate update.
     92
     93Added automatic & one click API certificate renewal. This grately improves user experience for maitaining the Identity Plus plugin and prevents accidental certificate expiration, which may cause service outage.
     94Integrated the new service installation proces via automated wizard. It is no longer needed for the user to log into identity plus account and issue certificate before installation. Using the mobile application, or registered device, you can now onboard the service, issue the certificate and activate identity plus in one short flow.
     95We've also moved the certificate storage from file to the database for enhanced security.
    8396
    8497== 1.6.4 ==
Note: See TracChangeset for help on using the changeset viewer.