Skip to content

Commit

Permalink
Updated README for Laravel 5 support
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisbjr committed Mar 27, 2015
1 parent 48e6593 commit f1e2fbd
Showing 1 changed file with 137 additions and 153 deletions.
290 changes: 137 additions & 153 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,121 +11,79 @@ A simple way of authenticating your APIs with API keys using Laravel. This packa
The concept for managing API keys is also taken from Phil Sturgeon's [codeigniter-restserver](https://github.com/philsturgeon/codeigniter-restserver).
I've been looking for an equivalent for Laravel but did not find any so this is an implementation for that.

## Quick start
## Laravel 5 is finally supported!

Various versions of api-guard:

**Laravel 5.0.x**: `2.0.*`

### Required setup
**Laravel 4.2.x**: [`1.0`](https://github.com/chrisbjr/api-guard/tree/v1.0) (Recently updated version for Laravel 4. Please note that there are namespace changes here)

NOTE: Currently, ApiGuard will only work for Laravel 4.2.*.
**Laravel 4.2.x**: [`0.*`](https://github.com/chrisbjr/api-guard/tree/v0.7) (The version that most of you are using)

## Quick start

In the `require` key of `composer.json` file add the following
### Laravel 5.0.x

"chrisbjr/api-guard": "0.*"
In the `require` key of your `composer.json` file add the following

"chrisbjr/api-guard": "2.0.*"

Run the Composer update comand

$ composer update

In your `config/app.php` add `'Chrisbjr\ApiGuard\ApiGuardServiceProvider'` to the end of the `$providers` array
In your `config/app.php` add `Chrisbjr\ApiGuard\Providers\ApiGuardServiceProvider` to the end of the `providers` array

```php
'providers' => array(

'Illuminate\Foundation\Providers\ArtisanServiceProvider',
'Illuminate\Auth\AuthServiceProvider',
...
'EllipseSynergie\ApiResponse\Laravel\ResponseServiceProvider',
'Chrisbjr\ApiGuard\ApiGuardServiceProvider',
'Chrisbjr\ApiGuard\Providers\ApiGuardServiceProvider',
),
```

Now generate the api-guard migration (make sure you have your database configuration set up correctly):

$ php artisan migrate --package="chrisbjr/api-guard"

It will setup two tables - api_keys and api_logs.
Now publish the migration and configuration files for api-guard:

### Generating your first API key

Once you're done with the required setup, you can now generate your first API key.

Make sure your Laravel installation is accessible through a web server - if not, you can use `artisan` to quickly bring up your Laravel installation by running the command below:

$ php artisan serve
$ php artisan vendor:publish --provider="Chrisbjr\ApiGuard\Providers\ApiGuardServiceProvider"

Then run the migration:

Once the web server is up, you can issue a POST request ApiGuard's pre-defined route for generating an API key. You can use `curl` in the command line as shown below:
$ php artisan migrate

$ curl -X POST http://localhost:8000/apiguard/api_key
It will setup two tables - api_keys and api_logs.

This will generate an API key and should return the following data:
### Laravel 4.2.x

```javascript
{
data: {
id: 9
user_id: 0
key: "7f03891b8f7c4ba10af2e0e37232f98fa2fc9a1a"
level: 10
ignore_limits: 1
created_at: {
date: "2014-06-26 12:07:49"
timezone_type: 3
timezone: "UTC"
}
updated_at: {
date: "2014-06-26 12:07:49"
timezone_type: 3
timezone: "UTC"
}
}
}
```
Note: Documentation for use with Laravel 4.2.x differs from Laravel 5.0.x. Please refer to the README [here](https://github.com/chrisbjr/api-guard/tree/v1.0). If you are using version `0.*` you can find the README [here](https://github.com/chrisbjr/api-guard/tree/v0.7)

Take note of your first API key.
### Generating your first API key

Now, to prevent others from generating API keys through the route above, you can disable this in ApiGuard's configuration file.
Once you're done with the required setup, you can now generate your first API key.

To create your own configuration file for ApiGuard, run the following command:
Run the following command to generate an API key:

$ php artisan config:publish chrisbjr/api-guard
`php artisan api-key:generate`

The configuration file will be found in `app/config/packages/chrisbjr/api-guard/config.php`. Open this file and change the `generateApiKeyRoute` variable to `false`
Generally, you will want to generate API keys for each user in your application. The `api_keys` table has a `user_id` field which you can populate for your users.

'generateApiKeyRoute' => false
To generate an API key that is linked to a user, you can do the following:

Generally, you will want to generate API keys for each user in your application. The `api_keys` table has a `user_id` field which you can populate for your users.
`php artisan api-key:generate --user-id=1`

## Usage

Basic usage of ApiGuard is to create a controller and extend that class to use the `ApiGuardController`.

Note: The namespace of the `ApiGuardController` differs from previous versions.

```php
<?php
use Chrisbjr\ApiGuard\ApiGuardController;

use Chrisbjr\ApiGuard\Http\Controllers\ApiGuardController;

class BooksController extends ApiGuardController
{
protected $apiMethods = [
'all' => [
'keyAuthentication' => true,
'level' => 1,
'limits' => [
// The variable below sets API key limits
'key' => [
'increment' => '1 hour',
'limit' => 100
],
// The variable below sets API method limits
'method' => [
'increment' => '1 day',
'limit' => 1000
]
]
],

'show' => [
'keyAuthentication' => false
]
];

public function all()
{
Expand All @@ -137,22 +95,25 @@ class BooksController extends ApiGuardController
public function show($id)
{
try {

$book = Book::findOrFail($id);

return $this->response->withItem($book, new BookTransformer);

} catch (ModelNotFoundException $e) {

return $this->response->errorNotFound();

}
}

}
```

Notice the `$apiMethods` variable. You can set `limits`s , `level`s, and `keyAuthentication` for each method here.
If you don't specify any, the defaults would be that no limits would be implemented, no level access, and key authentication would be required.

You should also be able to use the api-response object by using `$this->response`. More examples can be found on the Github page: [https://github.com/ellipsesynergie/api-response](https://github.com/ellipsesynergie/api-response).
You should be able to use the api-response object by using `$this->response`. More examples can be found on the Github page: [https://github.com/ellipsesynergie/api-response](https://github.com/ellipsesynergie/api-response).

You can access the above controller by creating a basic route in your `app/routes.php`:

```php
Route::get('api/v1/books', 'BooksController@all');
Route::get('api/v1/books/{id}', 'BooksController@show');
Expand All @@ -165,6 +126,7 @@ Try calling this route using `curl`
curl --header "X-Authorization: 2ed9d72e5596800bf805ca1c735e446df72019ef" http://localhost:8000/api/v1/books

You should get the following response:

```javascript
{
"data": {
Expand All @@ -185,101 +147,123 @@ You should get the following response:
}
```

### Accessing the User instance and Stateless authentication
## API Options

There are various options that can be specified for each method in your controller. These options can be specified inside the `$apiMethods` variable. Examples can be found below.

You can easily access the User instance from the belongsTo() relationship of the ApiKey model to the User class. With this, we can implement API based authentication with the following as an example.
### Turning off API key authentication for a specific method

Note that while we have utilized [Confide](https://github.com/zizaco/confide) for handling the credential checking, you can have your own way of having this done (like using the native Laravel Auth class, or [Sentry](https://github.com/cartalyst/sentry) for that matter).
By default, all the methods in the ApiGuardController will be authenticated. To turn this off for a specific method, use the `keyAuthentication` option.

```php
<?php namespace api\v1;
<?php

use Chrisbjr\ApiGuard\ApiGuardController;
use Chrisbjr\ApiGuard\ApiKey;
use Chrisbjr\ApiGuard\Transformers\ApiKeyTransformer;
use Confide;
use Input;
use User;
use Validator;
use Chrisbjr\ApiGuard\Http\Controllers\ApiGuardController;

class UserApiController extends ApiGuardController
class BooksController extends ApiGuardController
{

protected $apiMethods = [
'authenticate' => [
'show' => [
'keyAuthentication' => false
]
],
];

public function authenticate() {
$credentials['username'] = Input::json('username');
$credentials['password'] = Input::json('password');

$validator = Validator::make([
'username' => $credentials['username'],
'password' => $credentials['password']
],
[
'username' => 'required|max:255',
'password' => 'required|max:255'
]
);
...

if ($validator->fails()) {
return $this->response->errorWrongArgsValidator($validator);
}
}
```

try {
$user = User::whereUsername($credentials['username'])->first();
$credentials['email'] = $user->email;
} catch (\ErrorException $e) {
return $this->response->errorUnauthorized("Your username or password is incorrect");
}
This above example will turn off key authentication for the `show` method.

if (Confide::logAttempt($credentials) == false) {
return $this->response->errorUnauthorized("Your username or password is incorrect");
}
### Specifying access levels for API methods

// We have validated this user
// Assign an API key for this session
$apiKey = ApiKey::where('user_id', '=', $user->id)->first();
if (!isset($apiKey)) {
$apiKey = new ApiKey;
$apiKey->user_id = $user->id;
$apiKey->key = $apiKey->generateKey();
$apiKey->level = 5;
$apiKey->ignore_limits = 0;
} else {
$apiKey->generateKey();
}
If you take a look at the `api_keys` table in your database, you will notice that there is a `level` field.

if (!$apiKey->save()) {
return $this->response->errorInternalError("Failed to create an API key. Please try again.");
}
This will allow you to specify a level for your API key and if the method has a higher level than the API key, access will be restricted. Here is an example on how to set the level on a method:

// We have an API key.. i guess we only need to return that.
return $this->response->withItem($apiKey, new ApiKeyTransformer);
}
```php
<?php

public function getUserDetails() {
$user = $this->apiKey->user;
use Chrisbjr\ApiGuard\Http\Controllers\ApiGuardController;

return isset($user) ? $user : $this->response->errorNotFound();
}
class BooksController extends ApiGuardController
{

public function deauthenticate() {
if (empty($this->apiKey)) {
return $this->response->errorUnauthorized("There is no such user to deauthenticate.");
}
protected $apiMethods = [
'show' => [
'level' => 10
],
];

...

}
```

Now if your API key has a level of 9 or lower, then access to the `show` method will be restricted.

$this->apiKey->delete();
### Limiting API key access rate

return $this->response->withArray([
'ok' => [
'code' => 'SUCCESSFUL',
'http_code' => 200,
'message' => 'User was successfuly deauthenticated'
You can limit the rate at which an API key can have access to a particular method by using the `limits.key` option.


```php
<?php

use Chrisbjr\ApiGuard\Http\Controllers\ApiGuardController;

class BooksController extends ApiGuardController
{

protected $apiMethods = [
'show' => [
'limits' => [
'key' => [
'increment' => '1 hour',
'limit' => 100
]
]
]);
}
],
];

...

}
```

The above example will limit the access to the `show` method of an API key to 100 requests for every hour.

Note: The `increment` option can be any value that is accepted by the `strtotime()` method.

### Limiting access to a method

There is also an option to limit the request rate for a given method no matter what API key is used. For this, we use the `limits.method` option.

```php
<?php

use Chrisbjr\ApiGuard\Http\Controllers\ApiGuardController;

class BooksController extends ApiGuardController
{

protected $apiMethods = [
'show' => [
'limits' => [
'method' => [
'increment' => '1 day',
'limit' => 1000
]
]
],
];

...

}
```

The above example will limit the request rate to the `show` method to 1000 requests per day.

Note: The `increment` option can be any value that is accepted by the `strtotime()` method.

0 comments on commit f1e2fbd

Please sign in to comment.