Session class error that requires an encryption key in codeigniter - php

I'm new to codeigniter and have an okay experience with php. I recently encountered an error where codeigniter tells me
"In order to use the Session class you are required to set an encryption key in your config file."
And I heard the solution was to paste in
$config['encryption_key'] = 'your_encryption_key_here';
in the config file.
Now I have absolutely no idea what just happened here. What is this encryption key? Why is it required for session class and what's the point?
Thank you everyone.

From the Session class documentation:
Note: Even if you are not using encrypted sessions, you must set an encryption key in your config file which is used to aid in preventing session data manipulation.
Also, you shouldn't need to paste anything. $config['encryption_key'] already exists in config.php but is set to an empty string:
/*
|--------------------------------------------------------------------------
| Encryption Key
|--------------------------------------------------------------------------
|
| If you use the Encryption class or the Session class you
| MUST set an encryption key. See the user guide for info.
|
*/
$config['encryption_key'] = '';

Related

What is the significance of Application key in a Laravel Application?

from laravel docs
Application Key The next thing you should do after installing Laravel
is set your application key to a random string. If you installed
Laravel via Composer or the Laravel installer, this key has already
been set for you by the php artisan key:generate command.
Typically, this string should be 32 characters long. The key can be
set in the .env environment file. If you have not renamed the
.env.example file to .env, you should do that now. If the application
key is not set, your user sessions and other encrypted data will not
be secure!
What I know about application key is: If the application key is not set, generally I do get an exception.
How do this random string help to secure the session?
What are the other uses of this application key?
If I use the same application key everywhere (like staging, production etc..) does it make the application less secure?
what are some best practices for this key
As we can see its used in EncryptionServiceProvider:
public function register()
{
$this->app->singleton('encrypter', function ($app) {
$config = $app->make('config')->get('app');
// If the key starts with "base64:", we will need to decode the key before handing
// it off to the encrypter. Keys may be base-64 encoded for presentation and we
// want to make sure to convert them back to the raw bytes before encrypting.
if (Str::startsWith($key = $this->key($config), 'base64:')) {
$key = base64_decode(substr($key, 7));
}
return new Encrypter($key, $config['cipher']);
});
}
So every component that uses encryption: session, encryption (user scope), csrf token benefit from the app_key.
Rest of the questions can be answered by "how encryption" (AES) works, just open up Encrypter.php, and confirm that Laravel uses AES under the hood and encodes the result to base64.
Further more we can see how its all done by using tinker:
➜ laravel git:(staging) ✗ art tinker
Psy Shell v0.8.17 (PHP 7.1.14 — cli) by Justin Hileman
>>> encrypt('Hello World!')
=> "eyJpdiI6ImgzK08zSDQyMUE1T1NMVThERjQzdEE9PSIsInZhbHVlIjoiYzlZTk1td0JJZGtrS2luMlo0QzdGcVpKdTEzTWsxeFB6ME5pT1NmaGlQaz0iLCJtYWMiOiI3YTAzY2IxZjBiM2IyNDZiYzljZGJjNTczYzA3MGRjN2U3ZmFkMTVmMWRhMjcwMTRlODk5YTg5ZmM2YjBjMGNlIn0="
Note: I used this key: base64:Qc25VgXJ8CEkp790nqF+eEocRk1o7Yp0lM1jWPUuocQ= to encrypt Hello World!
After decoding the result we get (you can try decode your own cookie with session):
{"iv":"h3+O3H421A5OSLU8DF43tA==","value":"c9YNMmwBIdkkKin2Z4C7FqZJu13Mk1xPz0NiOSfhiPk=","mac":"7a03cb1f0b3b246bc9cdbc573c070dc7e7fad15f1da27014e899a89fc6b0c0ce"}
to understand above json (iv, value, mac) you need to understand AES:
https://en.wikipedia.org/wiki/Advanced_Encryption_Standard
Best practices for application key
do store it in .env file only
do not store it in app.php, in fact in any git tracked file
do not change it unless you really want to
invalidate sessions/cookies (user logout)
invalidate password reset tokens
invalidate signed urls
Obvious Note: Changing application key has no effect on hashed passwords since hashing algorithms do not require encryption keys.

Dynamic Encryption key in CodeIgniter 3 config

I am trying to follow the instruction of CI 3 docs about encryption https://codeigniter.com/userguide3/libraries/encryption.html#setting-your-encryption-key I apply the instruction but it won't make pretty output like I want, here is the standard code
$this->load->library('encryption');
$key = $this->encryption->create_key(16);
// Get a hex-encoded representation of the key:
$key = bin2hex($this->encryption->create_key(16));
// Put the same value in your config with hex2bin(),
// so that it is still passed as binary to the library:
$config['encryption_key'] = hex2bin(<your hex-encoded key>);
but i am getting this error
how to solve this error? or I am writing some wrong code?
If you use the Encryption class, you must set an encryption key. and dynamic Encryption key must be set on indivisible controller file.single Encryption key set on config.php file
//single encryption key
$config['encryption_key'] = '';
//dynamic encryption key
$this->load->library('encryption'); //load encryption library in your controller
$key = bin2hex($this->encryption->create_key(16));
$config['encryption_key'] = hex2bin();

Laravel 4.2 package development on top of Authorize.net SKD - where to put Constant Variables?

I'm developing my first Laravel package in workbench to solve a business need which is to integrate the Authorize.net SDK for our systems billing transactions.
I've got most of my code now working and I can call the SDK functions via my custom facade like so AuthorizeMe::authorizeAndCapture(); My issue is the Authroize.net SDK requires use of defined variables. Their example usage is as follows:
define("AUTHORIZENET_API_LOGIN_ID", "YOURLOGIN");
define("AUTHORIZENET_TRANSACTION_KEY", "YOURKEY");
define("AUTHORIZENET_SANDBOX", true);
$sale = new AuthorizeNetAIM;
$sale->amount = "5.99";
$sale->card_num = '6011000000000012';
$sale->exp_date = '04/15';
$response = $sale->authorizeAndCapture();
if ($response->approved) {
$transaction_id = $response->transaction_id;
}
I would like to 1) store the defined variables in the packages config.php file, 2) I would like to make it so if I do publish the package other users can simply publish the config file to their app/config/packages folder so they can simply put in their unique api info.
I have tried to store the API variables in the config.php array as follows:
return array(
/*
|--------------------------------------------------------------------------
| Define credentials
|--------------------------------------------------------------------------
|
| Your credentials for both live environment and sandbox
|
*/
// Live environment
'LIVE_LOGIN_ID' => 'YOUR ID',
'LIVE_TRANSACTION_KEY' => 'YOUR KEY',
// Sandbox evnironment
'SANDBOX_LOGIN_ID' => 'YOUR SANDBOX ID',
'SANDBOX_TRANSACTION_KEY' => 'YOUR SANDBOX KEY',
/*
|--------------------------------------------------------------------------
| Define environment
|--------------------------------------------------------------------------
|
| Dictates if we're in sandbox mode or live mode
|
*/
'SANDBOX' => true,
);
I don't believe defined variables can be set from within a class so I'm not sure how to use the config file to accomplish my needs.
For example, something like this doesn't seem to work:
class MyClass {
public function __construct($app=null)
{
$this->app = $app ?: app();
}
public function billClient()
{
define("LIVE_LOGIN_ID", $this->app['config']->get('LIVE_LOGIN_ID'));
}
}
Lastly, I don't want to re-write the vendors package to simply work with my implementation as I feel it's important to make sure my package wrapper just sits on top so that it can pull in any future updates.
Store your static data that can change depending on what server your software is running on inside of the environment root-level configuration file. I would suggest doing this also to avoid the possibility of your API keys getting committed into source control (which could potentially be damaging). You can also leverage this to have different configuration values in different environments. Quoting from that linked to manual entry:
For "real" applications, it is advisable to keep all of your sensitive configuration out of your configuration files. Things such as database passwords, Stripe API keys, and encryption keys should be kept out of your configuration files whenever possible
The general practice is to keep these defined in a config file named .env.{environment name}.php which does not get checked in to source control. You can also specify them inside of the virtual host for the site if that works better for you, with e.g. SetEnv directives for Apache.

How to integrate CKFinder with Laravel?

I'm trying to integrate CKFinder with Laravel, and I'm about 95% there. I can get everything to work, except for the CheckAuthentication function - I have to make it return true regardless for the upload to work.
What I've tried doing is bootstrapping Laravel in the config.php file and then checking if a user is logged in, like below:
public/packages/ckfinder/config.php
<?php
/*
* ### CKFinder : Configuration File - Basic Instructions
*
* In a generic usage case, the following tasks must be done to configure
* CKFinder:
* 1. Check the $baseUrl and $baseDir variables;
* 2. If available, paste your license key in the "LicenseKey" setting;
* 3. Create the CheckAuthentication() function that enables CKFinder for authenticated users;
*
* Other settings may be left with their default values, or used to control
* advanced features of CKFinder.
*/
/** RIPPED FROM public/index.php **/
/*
|--------------------------------------------------------------------------
| Register The Auto Loader
|--------------------------------------------------------------------------
|
| Composer provides a convenient, automatically generated class loader
| for our application. We just need to utilize it! We'll require it
| into the script here so that we do not have to worry about the
| loading of any our classes "manually". Feels great to relax.
|
*/
require __DIR__.'/../../../bootstrap/autoload.php';
/*
|--------------------------------------------------------------------------
| Turn On The Lights
|--------------------------------------------------------------------------
|
| We need to illuminate PHP development, so let's turn on the lights.
| This bootstraps the framework and gets it ready for use, then it
| will load up this application so that we can run it and send
| the responses back to the browser and delight these users.
|
*/
$app = require __DIR__.'/../../../bootstrap/start.php';
/** END public/index.php **/
/**
* This function must check the user session to be sure that he/she is
* authorized to upload and access files in the File Browser.
*
* #return boolean
*/
function CheckAuthentication()
{
// WARNING : DO NOT simply return "true". By doing so, you are allowing
// "anyone" to upload and list the files in your server. You must implement
// some kind of session validation here. Even something very simple as...
return Auth::check();
}
This always returns false, though. I've also tried directly using Laravel's Session to set a variable to true when someone logs in, and false when they log out, and then checking that in the config.php file, but it always returns the default value in Session::get("IsAuthorized", false);. Can anyone offer some guidance as to -
1) How to authenticate whether the user should be allowed to upload?
2) Why bootstrapping Laravel in another file seems to cause it to use a separate session, even when it's loading the same files?
I tried integrating simogeo's Filemanager and KCFinder into a Laravel project and I found the same problem.
With this code, it's possible to share Laravel's session and check authentication from external projects:
https://gist.github.com/frzsombor/ddd0e11f93885060ef35
From my experience, starting from 4.1.28, Application::boot() does not initialize sensitive session data anymore.
So if you're integrating 3rd party library, which needs external authentification check through sessions, simple checking Auth::check() will not work. However, we can still use old $_SESSION variable.
E.g. this one will not work:
require __DIR__.'/../bootstrap/autoload.php';
$app = require_once __DIR__.'/../bootstrap/start.php';
$app->boot();
return Auth::check();
Session variables for Auth::check() to work are initialized only in $app->run() sequence. But in that case, routing will take place and probably you will get unrecognized page... unless you're using dedicated Laravel package for this.
This one - below - still works:
// Somewhere in your app - e.g. in filters.php, "auth"/"guest" filters declaration
if (session_id() == '') {
#session_start();
/* or Session:start(); */
}
$_SESSION['isLoggedIn'] = Auth::check() ? true : false;
Then in your case, function would be simple as:
function CheckAuthentication()
{
if (session_id() == '') {
#session_start();
}
return isset( $_SESSION['isLoggedIn'] ) && $_SESSION['isLoggedIn'] == true;
}
N.B. If you can use Ajax calls for authorization checks, you can still make a custom API with JSON request to user-logged (as an example) to see if user is authentificated.
To answer your second question - it's not so simple as it sounds. Laravel, as a default, uses file system for session storage. While session data is still accessible, it is encrypted - unless you will write your own Session manager, you can't extract anything from there easily.

Laravel sessions not available in native PHP?

New to Laravel and having some problems with Sessions. Specifically, reading session data from a PHP file outside of Laravel.
For example, let's say I set the session variable like so: Session::put('isAuthorized', 'yes') - I can retrieve this just fine in the Laravel context with Session::get('isAuthorized') but the following PHP will not retrieve this session key -
<?php
session_start();
echo $_SESSION['isAuthorized'];
?>
returns
Notice: Undefined index: isAuthorized in C:\xampp\htdocs\session.php on line 3
I have tried setting the Laravel session driver to both the default cookie and file modes, same result.
You could also write a session adapter, so the $_SESSION variable will be an instance of it:
<?php
class SessionAdapter implements \ArrayAccess {
public function offsetExists($offset) {
return Session::has($offset);
}
public function offsetGet($offset) {
return Session::get($offset);
}
public function offsetSet($offset, $value) {
return Session::put($offset, $value);
}
public function offsetUnset($offset) {
return Session::forget($offset);
}
}
And then somewhere in your code:
<?php
$_SESSION = new SessionAdapter();
// or
$GLOBALS['_SESSION'] = new SessionAdapter();
This way native PHP session and Laravel session will be "the same".
Laravel uses storage drivers for its sessions, namely cookie, file, database, memory, memcached and redis (and APC in Laravel 4).
The web is a stateless environment. This means that each request to your application is considered unrelated to any previous request. However, sessions allow you to store arbitrary data for each visitor to your application. The session data for each visitor is stored on your web server, while a cookie containing a session ID is stored on the visitor's machine. This cookie allows your application to "remember" the session for that user and retrieve their session data on subsequent requests to your application.
http://laravel.com/docs/session/config
The default storage driver is Cookie, so try this:
print_r($_COOKIE);
Please note that this answer is specific to Laravel 3
Laravel doesn't use PHP sessions, so forget session_start(), $_SESSION, etc.
If you're running with file session driver, the session data is stored in a file in storage/sessions. You can obtain the name of the file by reading the Laravel session ID from the cookie. So the hacky way to solve your problem would be to write some code that obtains the session ID from the cookie and then looks for the file with that name in the storage/sessions folder, read that file in, json_decode() it and you can read the whole thing.
If you're running with cookie session driver, all of the session data is stored in the cookie, but it is encrypted, so you'd have to have a copy of the key (which should be in application/config/application.php) and then figure out what encryption method Laravel is using so you can decrypt it. Then you can read all the session variables.
To achieve what you're hoping to achieve - that is, figure out if the current person is authorized, it might be better to build an API into your app and secure it so that it can only be accessed by localhost. Not a great solution from a performance standpoint, but potentially more elegant because you're not hacking around with the internals of Laravel session management.
Session handling in Laravel is indeed different from native PHP session. To use native PHP session, set the value as below:
<?php
session_start();
$_SESSION['isAuthorized'] = 'yes';
echo $_SESSION['isAuthorized']; // output yes
?>

Categories