Security News
Introducing the Socket Python SDK
The initial version of the Socket Python SDK is now on PyPI, enabling developers to more easily interact with the Socket REST API in Python projects.
oauthio-server
Advanced tools
This SDK allows you to use the OAuth 2.0 providing features of OAuth.io.
OAuth 2.0 allows you to add an authentication layer to your API, according the the RFC 6749.
Create a provider on OAuth.io/oauthd
First, you need to create a provider on OAuth.io, or in your oauthd instance.
There you will be able to configure the provider with a name, and a complete authorization items list (with which clients will define their scope).
You'll be able to retrieve the provider_id and the provider_secret, which will enable you to initialize the SDK on your node.js API server.
User management
Your server must have some kind of user management, as client applications will use your API on behalf of your users.
To install the SDK, just run the following command in your API server application:
$ node install oauthio-provider
###Introduction
The OAuth 2.0 framework allows you to secure your API endpoints with an authentication layer. This lets apps call the endpoints on behalf of your users, after having asked for a scope of permissions.
The authentication is done thanks to an access token, which is given with any call to the API.
The token is recognized, and the associated user, associated app and the available permissions scope are found so the API is able to decide if it will send resource or not.
To obtain the access token, the following processs is used:
/authorize
endpoint) with information about who the client is/token
endpoint on the provider's API.Implementing all this, be it from the client's point of view, or from the provider's, is quite long and tedious.
For the client part, check out OAuth.io and oauthd's client services, which will enable you to integrate over 100 APIs in your application in a matter of minutes.
###Initializing the SDK
Once you have created a provider on OAuth.io or oauthd, and installed the SDK via npm, you need to initialize the SDK with your provider_id and provider_secret:
OAuthProviding = require('oauthio-oauth-providing');
OAuthProviding.initialize('your_provider_id', 'your_provider_secret');
Once that's done, you will be able to create the endpoints for the OAuth 2.0 dance, and use the client management methods to create and edit your client apps from your developer portal.
###OAuth 2.0 dance endpoints
####Recognizing the user
The first thing you need to do is to provide the SDK a way to recognize your currently logged in user from a connect request object, by overriding the OAuth2.getUserId
method. For example, if the user id is stored in the session , you can do something like this:
OAuthProvider.OAuth2.getUserId = (req) ->
return req.session.user.id
####Authorize
Then you'll need to create two endpoints for the /authorize
URL. You can put another URL if you want, but /authorize
is recommended by the OAuth 2.0 RFC.
GET /authorize
First, you need to create an endpoint for the GET
method, which will redirect the user to a login page if he is not logged in, and show the decision form if he is.
If the user is not logged in, you need to redirect him to the log in page with the same GET parameters, and the location of the authorization endpoint. Once the user is logged in, he should be redirected once more to the authorization endpoint with the original get parameters.
Here's an example of how you could do it:
// authorization endpoint login middleware
var isLoggedIn = function (req, res, next) {
if (req.session.user) {
// if the user is connected, continue to the authorization endpoint
next();
} else {
// otherwise, redirect him to the login endpoint
// the backUrl variable will enable the login endpoint
// to redirect to the authorization page once the user is logged in
var backUrl = req.path;
// appends the backUrl to the GET parameters
req.query.backUrl = backUrl;
// the qs stringify transforms an object in
// a url ready parameters string
var parameters = qs.stringify(req.query);
res.redirect('/login?' + parameters);
}
};
// Log in page
app.get('/login', function (req, res, next) {
// serve the login page, for example:
res.sendFile(__dirname + '/templates/login.html');
});
// Login form action
app.post('/login', function (req, res, next) {
// login the user (of course this is simplified ;) )
if (req.body.username == 'theuser' and req.body.password == 'thepassword') {
req.session.user = {
id: 'theuserid',
username: 'theuser'
}
// redirect to backUrl, with the same GET parameters
var backUrl = req.query.backUrl;
delete req.query.backUrl;
var parameters = qs.stringify(req.query);
res.redirect('/authorize?' + parameters);
} else {
res.status(500);
res.send("Wrond username or password");
}
});
The authorization endpoint uses the isLoggedIn
middleware. The endpoint must then respond to the user with a decision form.
You can completely customize this form by giving a template path. The template will be parsed using ejs. By default, the template has access to the following variables:
client
: An object representing the client, containing the field name,scope
: An array containing the different permissions that the provider requestsYou can add custom values to the template as well.
To provider the endpoint with the template and custom data, you need to add a middleware, and override the req.template
field with the template path, and the req.data
field with an object containing values that will be usable in the template. Finally, you need to pass the result of OAuthProvider.OAuth2.getauthorize()
, which finishes the endpoint response:
app.get('/authorization', isLoggedIn, funtion (req, res, next) {
req.template = Path.join(__dirname + '/path/to/decision.html');
req.data = {
user: req.session.user
};
next();
}, OAuthProvider.OAuth2.getauthorize());
The template should contain a form with a field decision
valued 0 or 1 according to the user's response, for example:
<!DOCTYPE html>
<html>
<head><title>Decision page</title></head>
<body>
<p>
Hello, <%= user.username %>!
</p>
<p>
<%= client.name %> requests the following permissions to access your account on [Provider Name]:
<ul>
<% for (var k in scope) {%>
<li><%= scope[k] %></li>
<% } %>
</ul>
</p>
<!-- The forms should have no 'action' attribute, as it must call the same endpoint '/authorization' with the same GET parameters-->
<form method="POST">
<input type="hidden" name="decision" value="1" />
<input type="submit" value="Authorize" />
</form>
<form method="POST">
<input type="hidden" name="decision" value="0" />
<input type="submit" value="Cancel" />
</form>
</body>
</html>
POST /authorize
From here, things are a lot easier. You need to create the POST /authorize
and the POST /token
endpoints:
app.post('/authorize', OAuthProvider.OAuth2.postauthorize());
app.post('/token', OAuthProvider.OAuth2.token());
The POST /authorize
endpoint catches the response of the user to the decision form, and proxies it to OAuth.io's authentication server. This saves a set containing user's, id, the client and the scope, and associates it with an code. It redirects the user to the client's redirect URL with the code.
The client can then call the /token
endpoint with the code, the client id and client secret to get the access token server side.
And that's it. Now you can secure your API endpoints, filtering the calls thanks to the scope and user id associated with the access token.
###Securing your API endpoints
Here's how you can secure your API endpoints with this SDK's middleware, OAuthProvider.OAuth2.check()
:
// Using the OAuthProvider.OAuth2.check() middleware, you get
// all the information about the access token that was sent
// alongside the request
app.get('/someendpoint', OAuthProvider.OAuth2.check({
scope: ['list', 'of', 'required', 'permissions']
}), function (req, res, next) {
// if the provided access token does not have all the required permissions
// a 403 error is sent, otherwise, the endpoint is called
// Here you can get
// the user id
var user_id = req.OAuth2.userId;
// the client id
var client = req.OAuth2.clientId;
// the scope
var scope = req.OAuth2.scope;
response = {
key: 'value'
};
// if you need to check additional permissions
// you can use the scope variable:
if (scope.indexOf('additional_permission') !== -1) {
// add other information to the response
response.protectedKey = 'protectedValue';
}
// Finally send the response
res.status(200);
res.send(response);
});
###Managing your clients
The SDK gives you methods that simplify the access to the Client Management API that goes along the OAuth 2.0 server.
This way, you can create your own developer portal, so that developers can register their apps and use your platform.
All the client methods are contained in OAuthProvider.clients
.
####Creating a client
To create a client, you need to call the OAuthProvider.clients.create()
method, with a client's information.
Required fields
name
: The client's nameredirectUri
: The callback URI, on the client's domain, that will intercept the code to later exchange it for an access tokenOptional fields
description
: The client's descriptionExample
OAuthProvider.clients.create({
req.body
})
.then(function (client) {
// client created
// here you'll also have client.client_id and client.client_secret
})
.fail(function (error) {
// an error occured
});
####Retrieving all clients
To retrieve all your clients, you need to call the OAuthProvider.clients.getAll()
method.
Example
OAuthProvider.clients.getAll()
.then(function (clients){
// 'clients' contains all your clients
})
.fail(function (error) {
// an error occured
});
####Retrieving a specific client
To retrieve a specific client, you need to call the OAuthProvider.clients.get()
method with the client id of the requested client.
Example
OAuthProvider.clients.get(client_id)
.then(function (client){
// Here you'll have all the client's information
// in the 'client' variable
})
.fail(function (error) {
// an error occured
});
####Updating a client
To update a client, you need to call the OAuthProvider.clients.update()
with the client's updated data.
Required fields
client_id
: The id of the client to updateOptional fields
name
: the client's namedescription
: the client's descriptionExample
OAuthProvider.clients.update(client)
.then(function (client) {
// client was updated
})
.fail(function (error) {
// an error occured
});
####Resetting a client's keys
To reset a client's keys, you need to call the OAuthProvider.clients.regenerateKeys()
method with the client's client_id
.
Example
OAuthProvider.clients.regenerateKeys(client_id)
.then(function (client) {
// client keys were updated
})
.fail(function (error) {
// an error occured
});
####Deleting a client
To delete a client, you need to call the OAuthProvider.clients.delete()
method with the client's client_id
.
Example
OAuthProvider.clients.delete(client_id)
.then(function (client) {
// client keys were updated
})
.fail(function (error) {
// an error occured
});
To contribute to this SDK, you can:
This SDK is published under the Apache 2.0 license.
FAQs
OAuth that just works - for providers
The npm package oauthio-server receives a total of 0 weekly downloads. As such, oauthio-server popularity was classified as not popular.
We found that oauthio-server demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
The initial version of the Socket Python SDK is now on PyPI, enabling developers to more easily interact with the Socket REST API in Python projects.
Security News
Floating dependency ranges in npm can introduce instability and security risks into your project by allowing unverified or incompatible versions to be installed automatically, leading to unpredictable behavior and potential conflicts.
Security News
A new Rust RFC proposes "Trusted Publishing" for Crates.io, introducing short-lived access tokens via OIDC to improve security and reduce risks associated with long-lived API tokens.