Giter Club home page Giter Club logo

oz's Introduction

oz Logo

Oz is a web authorization protocol based on industry best practices. Oz combines the Hawk authentication protocol with the Iron encryption protocol to provide a simple to use and secure solution for granting and authenticating third-party access to an API on behalf of a user or an application.

Protocol version: 5.0.0 (Same as v1.0.0 but moved the expired ticket indicator from a header attribute to the error payload).

Build Status

Table of Content

Protocol

Oz builds on the well-understood concepts behind the OAuth protocol. While the terminology has been updated to reflect the common terms used today when building applications with third-party access, the overall architecture is the same. This document assumes the reader is familiar with the OAuth 1.0a protocol workflow.

Workflow

  1. The application uses its previously issued Hawk credentials to authenticate with the server and request an application ticket. If valid, the server issues an application ticket.
  2. The application directs the user to grant it authorization by providing the user with its application identifier. The user authenticates with the server, reviews the authorization grant and its scope, and if approved the server returns an rsvp.
  3. The user returns to the application with the rsvp which the application uses to request a new user-specific ticket. If valid, the server returns a new ticket.
  4. The application uses the user-ticket to access the user's protected resources.

Application

Oz is an application-to-server authorization protocol. This means credentials are issued only to applications, not to users. The method through which users authenticate is outside the scope of this protocol.

The application represents a third-party accessing protected resource on the server. This third-party can be another server, a native app, a single-page-app, or any other application using web resources. The protected resources can be under the control of the application itself or under the control of a user who grants the application access.

Each application definition includes:

  • id - a unique application identifier.
  • scope - the default application scope.
  • delegate - if true, the application is allowed to delegate a ticket to another application. Defaults to false.

Applications must be registered with the server prior to using Oz. The method through which applications register is outside the scope of this protocol. When an application registers, it is issued a set of Hawk credentials. The application uses these credentials to obtain an Oz ticket.

The application Hawk credentials include:

  • id - the unique application identifier.
  • key - a shared secret used to authenticate.
  • algorithm - the HMAC algorithm used to authenticate (e.g. HMAC-SHA256).

The Hawk protocol supports two Oz-specific header attributes which are used for authenticating Oz applications (app and dlg).

User

Applications act on behalf of users. Users are usually people with protected resources on the server who would like to use the application to access those protected resources. For the purpose of the Oz protocol, each user must have a unique identifier which is used by the protocol to record access rights. The method through which users are registered, authenticated, and managed is beyond the scope of this protocol.

Ticket

An Oz ticket is a set of Hawk credentials used by the application to access protected resources. Just like any other Hawk credentials, the ticket includes:

  • id - a unique identifier for the authorized access.
  • key - a shared secret used to authenticate.
  • algorithm - the HMAC algorithm used to authenticate (e.g. HMAC-SHA256).

However, unlike most Hawk credential identifiers, the Oz identifier is an encoded Iron string which when decoded contains:

  • exp - ticket expiration time in milliseconds since 1/1/1970.
  • app - the application id the ticket was issued to.
  • user - the user id if the ticket represents access to user resources. If no user id is included, the ticket allows the application access to the application own resources only.
  • scope - the ticket scope. Defaults to [] if no scope is specified.
  • delegate - if false, the ticket cannot be delegated regardless of the application permissions. Defaults to true which means use the application permissions to delegate.
  • grant - if user is set, includes the grant identifier referencing the authorization granted by the user to the application. Can be a unique identifier or string encoding the grant information as long as the server is able to parse the information later.
  • dlg - if the ticket is the result of access delegation, the application id of the delegating application.
  • ext - custom server data where:
    • public - also made available to the application when the ticket is sent back.
    • private - available only within the encoded ticket.

When a ticket is generated and sent to the application by the server, the response includes all of the above properties with the exception of ext which is included but only with the content of ext.public if present.

The ticket expiration can be shorter than the grant expiration in which case, the application can reissue the ticket. This provides the ability to limit the time credentials are valid but allowing grants to have longer lifetime.

When tickets are reissued, they can be constrained to less scope or duration, and can also be issued to another application for access delegation.

Grant

A grant is the authorization given to an application by a user to access the user's protected resources. Grants can be persisted in a database (usually to support revocation) or can be self describing (using an encoded identifier). Each grant contains:

  • id - the grant identifier, allowing the server to retrieve or recreate the grant information.
  • exp - authorization expiration time in milliseconds since 1/1/1970.
  • user - the user id who the user who authorized access.
  • scope - the authorized scope. Defaults to the application scope if no scope is specified.

Scope

Scope is an array of strings, each represents an implementation-specific permission on the server. Each scope string adds additional permissions to the application (i.e. ['a', 'b'] grants the application access to both the 'a' and 'b' rights, individually).

Each application has a default scope which is included in the tickets issued to the application unless the grant specifies a subset of the application scope. Applications cannot be granted scopes not present in their default set.

Rsvp

When the user authorizes the application access request, the server issues an rsvp which is an encoded string containing the application identifier, the grant identifier, and an expiration.

API

The Oz public API is offered as a full toolkit to implement the protocol as-is or to modify it to fit custom security needs. Most implementations will only need to use the endpoints functions methods and the ticket.rsvp() method directly.

Shared objects

app object

An object describing an application where:

  • id - the application identifier.
  • scope - an array with the default application scope.
  • delegate - if true, the application is allowed to delegate a ticket to another application. Defaults to false.
  • key - the shared secret used to authenticate.
  • algorithm - the HMAC algorithm used to authenticate (e.g. HMAC-SHA256).

grant object

An object describing a user grant where:

  • id - the grant identifier.
  • app - the application identifier.
  • user - the user identifier.
  • exp - grant expiration time in milliseconds since 1/1/1970.
  • scope - an array with the scope granted by the user to the application.

ticket response

An object describing a ticket and its public properties:

  • id - the ticket identifier used for making authenticated Hawk requests.
  • key - a shared secret used to authenticate.
  • algorithm - the HMAC algorithm used to authenticate (e.g. HMAC-SHA256).
  • exp - ticket expiration time in milliseconds since 1/1/1970.
  • app - the application id the ticket was issued to.
  • user - the user id if the ticket represents access to user resources. If no user id is included, the ticket allows the application access to the application own resources only.
  • scope - the ticket scope. Defaults to [] if no scope is specified.
  • grant - if user is set, includes the grant identifier referencing the authorization granted by the user to the application. Can be a unique identifier or string encoding the grant information as long as the server is able to parse the information later.
  • delegate - if false, the ticket cannot be delegated regardless of the application permissions. Defaults to true which means use the application permissions to delegate.
  • dlg - if the ticket is the result of access delegation, the application id of the delegating application.
  • ext - custom server public data attached to the ticket.

Oz.client

Utilities used for making authenticated Oz requests.

Oz.client.header(uri, method, ticket, [options])

A convenience utility to generate the application Hawk request authorization header for making authenticated Oz requests where:

  • uri - the request URI.
  • method - the request HTTP method.
  • ticket - the authorization ticket.
  • options - additional Hawk Hawk.client.header() options.

new Oz.client.Connection(options)

Creates an oz client connection manager for easier access to protected resources. The client manages the ticket lifecycle and will automatically refresh the ticken when expired. Accepts the following options:

  • endpoints - an object containing the server protocol endpoints: app - the application credentials endpoint path. Defaults to '/oz/app'. reissue - the ticket reissue endpoint path. Defaults to '/oz/reissue'.
  • uri - required, the server full root uri without path (e.g. 'https://example.com').
  • credentials - required, the application hawk credentials.
await connection.request(path, ticket, options)

Requests a protected resource where:

  • path - the resource path (e.g. '/resource').
  • ticket - the application or user ticket. If the ticket is expired, it will automatically attempt to refresh it.
  • options - optional configuration object where:
    • method - the HTTP method (e.g. 'GET'). Defaults to 'GET'.
    • payload - the request payload object or string. Defaults to no payload.

Return value: { result, code, ticket } where: - result - the requested resource (parsed to object if JSON). - code - the HTTP response code. - ticket - the ticket used to make the request (may be different from the ticket provided when the ticket was expired and refreshed). - throws request errors.

await connection.app(path, options)

Requests a protected resource using a shared application ticket where:

  • path - the resource path (e.g. '/resource').
  • options - optional configuration object where:
    • method - the HTTP method (e.g. 'GET'). Defaults to 'GET'.
    • payload - the request payload object or string. Defaults to no payload.

Return value: { result, code, ticket } where: - result - the requested resource (parsed to object if JSON). - code - the HTTP response code. - ticket - the ticket used to make the request (may be different from the ticket provided when the ticket was expired and refreshed). - throws request errors.

Once an application ticket is obtained internally using the provided hawk credentials in the constructor, it will be reused by called to connection.app(). If it expires, it will automatically refresh and stored for future usage.

await connection.reissue(ticket)

Reissues (refresh) a ticket where:

  • ticket - the ticket being reissued.

Return value: the reissued ticket.

Oz.endpoints

The endpoint methods provide a complete HTTP request handler implementation which is designed to be plugged into an HTTP framework such as hapi. The scarecrow plugin provides an example of how these methods integrate with an existing server implementation.

Endpoints options

Each endpoint method accepts a set of options.

encryptionPassword

A required string used to generate the ticket encryption key. Must be kept confidential. The string must be the same across all Oz methods and deployments in order to allow the server to parse and generate compatible encoded strings.

The encryptionPassword value is passed directly to the Iron module which supports additional inputs for pre-generated encryption and integrity keys as well as password rotation.

loadAppFunc

The application lookup method using the signature async function(id) where:

  • id - the application identifier being requested.
  • the function must return an application object or throw an error;
loadGrantFunc

The grant lookup method using the signature async function(id) where:

  • id - the grant identifier being requested.
  • the function must return an object { grant, ext } or throw an error where:
    • grant - a grant object.
    • ext - an optional object used to include custom server data in the ticket and response where:
      • public - an object which is included in the response under ticket.ext and in the encoded ticket as ticket.ext.public.
      • private - an object which is included only in the encoded ticket as ticket.ext.private.

await endpoints.app(req, payload, options)

Authenticates an application request and if valid, issues an application ticket where:

  • req - the node HTTP server request object.
  • payload - this argument is ignored and is defined only to keep the endpoint method signature consistent with the other endpoints.
  • options - protocol configuration options where:
    • encryptionPassword - required.
    • loadAppFunc - required.
    • ticket - optional ticket options used for parsing and issuance.
    • hawk - optional Hawk configuration object. Defaults to the Hawk defaults.

Return value: a ticket response object or throws an error.

await endpoints.reissue(req, payload, options)

Reissue an existing ticket (the ticket used to authenticate the request) where:

  • req - the node HTTP server request object.
  • payload - The HTTP request payload fully parsed into an object with the following optional keys:
    • issueTo - a different application identifier than the one of the current application. Used to delegate access between applications. Defaults to the current application.
    • scope - an array of scope strings which must be a subset of the ticket's granted scope. Defaults to the original ticket scope.
  • options - protocol configuration options where:
    • encryptionPassword - required.
    • loadAppFunc - required.
    • loadGrantFunc - required.
    • ticket - optional ticket options used for parsing and issuance.
    • hawk - optional Hawk configuration object. Defaults to the Hawk defaults.

Return value: a ticket response object or throws an error.

await endpoints.rsvp(req, payload, options)

Authenticates an application request and if valid, exchanges the provided rsvp with a ticket where:

  • req - the node HTTP server request object.
  • payload - The HTTP request payload fully parsed into an object with the following keys:
    • rsvp - the required rsvp string provided to the user to bring back to the application after granting authorization.
  • options - protocol configuration options where:
    • encryptionPassword - required.
    • loadAppFunc - required.
    • loadGrantFunc - required.
    • ticket - optional ticket options used for parsing and issuance.
    • hawk - optional Hawk configuration object. Defaults to the Hawk defaults.

Return value: a ticket response object or throws an error.

Oz.hawk

Provides direct access to the underlying Hawk module.

Oz.scope

Scope manipulation utilities.

Oz.scope.validate(scope)

Validates a scope for proper structure (an array of unique strings) where:

  • scope - the array being validated.

Returns an Error is the scope failed validation, otherwise null for valid scope.

Oz.scope.isSubset(scope, subset)

Checks whether a scope is a subset of another where:

  • scope - the superset.
  • subset - the subset.

Returns true if the subset is fully contained with scope, otherwise `false.

Oz.server

Server implementation utilities.

await Oz.server.authenticate(req, encryptionPassword, options)

Authenticates an incoming request using Hawk and performs additional Oz-specific validations where: Authenticates an application request and if valid, issues an application ticket where:

  • req - the node HTTP server request object.
  • encryptionPassword - the ticket encryption password.
  • options - protocol configuration options where:
    • ticket - optional ticket options used for parsing and issuance.
    • hawk - optional Hawk configuration object. Defaults to the Hawk defaults.

Return value: { ticket, artifacts } or throws an error where: - ticket - the decoded ticket response object. - artifacts - Hawk protocol artifacts.

Oz.ticket

Ticket issuance, parsing, encoding, and re-issuance utilities.

Ticket options

The following are the supported ticket parsing and issuance options passed to the corresponding ticket methods. Each endpoint utilizes a different subset of these options but it is safe to pass one common object to all (it will ignore unused options):

  • ttl - when generating a ticket, sets the ticket lifetime in milliseconds. Defaults to 3600000 (1 hour) for tickets and 60000 (1 minutes) for rsvps.
  • delegate - if false, the ticket cannot be delegated regardless of the application permissions. Defaults to true which means use the application permissions to delegate.
  • iron - overrides the default Iron configuration.
  • keyBytes - the Hawk key length in bytes. Defaults to 32.
  • hmacAlgorithm - the Hawk HMAC algorithm. Defaults to sha256.
  • ext - an object used to provide custom server data to be included in the ticket (this option will be ignored when passed to an endpoint method and the loadGrantFunc function returns an ext value) where:
    • public - an object which is included in the response under ticket.ext and in the encoded ticket as ticket.ext.public.
    • private - an object which is included only in the encoded ticket as ticket.ext.private.

await ticket.issue(app, grant, encryptionPassword, options)

Issues a new application or user ticket where:

  • app - the application object the ticket is being issued to.
  • grant - the grant object the ticket is being issued with if the ticket represents user access. null if the ticket is an application-only ticket.
  • encryptionPassword - the ticket encryption password.
  • options - ticket generation options.

Return value: a ticket response object.

await ticket.reissue(parentTicket, grant, encryptionPassword, options)

Reissues a application or user ticket where:

  • parentTicket - the ticket object being reissued.
  • grant - the grant object the ticket is being issued with if the ticket represents user access. null if the ticket is an application-only ticket.
  • encryptionPassword - the ticket encryption password.
  • options - ticket generation options.

Return value: a ticket response object or throws an error.

await ticket.rsvp(app, grant, encryptionPassword, options)

Generates an rsvp string representing a user grant where:

  • app - the application object the ticket is being issued to.
  • grant - the grant object the ticket is being issued with if the ticket represents user access. null if the ticket is an application-only ticket.
  • encryptionPassword - the ticket encryption password.
  • options - ticket generation options.

Return value: the rsvp string or throws an error.

await ticket.generate(ticket, encryptionPassword, options)

Adds the cryptographic properties to a ticket and prepares the response where:

  • ticket - an incomplete ticket object with the following:
    • exp
    • app
    • user
    • scope
    • grant
    • dlg
  • encryptionPassword - the ticket encryption password.
  • options - ticket generation options.

Return value: the completed ticket response object or throws an error.

await ticket.parse(id, encryptionPassword, options)

Decodes a ticket identifier into a ticket response where:

  • id - the ticket id which contains the encoded ticket information.
  • encryptionPassword - the ticket encryption password.
  • options - ticket generation options.

Return value: a ticket response object or throws an error.

Security Considerations

The greatest sources of security risks are usually found not in Oz but in the policies and procedures surrounding its use. Implementers are strongly encouraged to assess how this protocol addresses their security requirements. This section includes an incomplete list of security considerations that must be reviewed and understood before deploying Oz on the server. Most of these security considerations are the same as the security considerations for Hawk, and many of the protections provided in Hawk depend on whether or not they are used and how they are used.

Ticket and Application Hawk Credentials Transmission

Oz does not provide any mechanism for obtaining or transmitting the set of shared Hawk credentials for the application. Any mechanism the application uses to obtain the Hawk credentials must ensure that these transmissions are protected using transport-layer mechanisms such as TLS.

Plaintext Storage of Ticket and Application Hawk Credentials

The ticket keys and application Hawk keys in Oz function the same way passwords do in traditional authentication systems. In order to compute the request MAC, the server must have access to the key in plain-text form. This is in contrast, for example, to modern operating systems, which store only a one-way hash of user credentials.

If an attacker were to gain access to these keysβ€”or worse, to the server's database of all such keysβ€”he or she would be able to perform any action on behalf of the user. Accordingly, it is critical that servers protect these keys from unauthorized access.

Entropy of Keys

Unless a transport-layer security protocol is used, eavesdroppers will have full access to authenticated requests and request MAC values, and will thus be able to mount offline brute-force attacks to recover the key used. Servers should be careful to assign ticket keys and application Hawk keys that are long and random enough to resist such attacks for at least the length of time that the ticket credentials or the application Hawk credentials are valid.

For example, if the credentials are valid for two weeks, servers should ensure that it is not possible to mount a brute force attack that recovers the key in less than two weeks. Of course, servers are urged to err on the side of caution and use the longest key reasonable.

It is equally important that the pseudo-random number generator (PRNG) used to generate these keys be of sufficiently high quality. Many PRNG implementations generate number sequences that may appear to be random, but nevertheless exhibit patterns or other weaknesses which make cryptanalysis or brute force attacks easier. Implementers should be careful to use cryptographically secure PRNGs to avoid these problems.

Application Redirect URI

If the server redirects the RSVP to the application, the server should require a redirect URI for the application when the application is registered. This redirect URI would be used by the server to redirect back to the application with the RSVP after the user approves the grant. If the application supplies the redirect URI to the server and the server uses only this redirect URI to send the RSVP to the application, it is possible for an attacker to intercept the request from the application to server, change the supplied redirect URI to steal the RSVP, and exchange the RSVP for a user ticket if the application ticket credentials or application Hawk credentials were also stolen by the attacker. Additionally, the server requiring the registration of a redirect URI of an application adds an extra layer of security if the server redirects the RSVP to the application, because it limits what the attacker can do if he or she steals the application ticket credentials or application Hawk credentials.

oz's People

Contributors

geek avatar hueniverse avatar kidtronnix avatar shawm11 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

oz's Issues

Encryption password

Who is supposed to create and store the encryption password? Is it generated by the server (service provider) or the app (client)? Or is it the user's (resource owner's) password?

Oz.client.Connection in browser

I've been having issues using the Oz.client.Connection() utility in the browser. At first I was getting weird errors from Wreck because the stream was closed to soon. Then, after I upgraded to the latest Browserify I stopped getting any callbacks from request() at all (although the requests properly execute and are responded to according to the developer tools' network panel).

Is using Oz.client.Connection() intended to work in the browser, or has that use case intentionally been ruled out?

Desktop/mobile flow

The current version of Oz is best suited for server-to-server auth, because it uses redirect flow.

Previously you mentioned:

Right now Oz provides an OAuth 1.0-like workflow, but more workflows (especially for mobile) will be added soon.

Any update on that matter?

Thanks for the great repo, BTW!

Q: Why 'use' passwords?

You asked for questions in issue form, so here is one: Iron is based in deriving keys formencryption and authentication from a password with PBKDF. By default it uses a low iteration count.

I wonder why allow passwords at all. In a similar system I am using (hex encoded) completely random keys (and a tool to generate them together with a random Id). I derive the actual encryption keys with HKDF since I am sure there is no entropy problem with non-humanly chosen secrets.

How does delegation work?

Hi,

I cannot get delegation to work and I don't understand what I have to do.
I'm currently here:

  1. The user has a ticket to App A.
  2. The App A makes a request to the server on enpoint /reissue with issueTo to the App B identifier. (The request is authenticated with user ticket.)
  3. App A receives a new ticket with app and dlg that reflects the delegation.

Now I'm stuck. I've tried several thing. I.e. to send the delegated ticket to App B by HTTP POST. And then from App B use that ticket to authenticate with the server. But the server keeps responding Unauthorized.

What is the correct usage?

I know that @rs22 has proposed a rsvp-based delegation flow. ( #48) But I'm simply wondering how the delegation should work on the current Oz release.

Document current state of implementation in README

Hi,

I have been looking into the code and as I am not an expert, nor have examined the code, I would like to ask for the current state of the implementation. Any docs would also be great, but with an updated README would be enought.

Redirect endpoint in Oz: Does Oz have the same vulnerability as OAuth 2.0?

If I were to add a /oz/redirect endpoint on the server (service provider) for redirecting to an application. Does Oz now have the same vulnerability as OAuth 2.0 as described here and here?

For example, an application were to try to redirect to the server using its application ticket credentials by doing GET /oz/redirect?to=https://myapp.com. The server authenticates the user, and redirects back to the application by doing GET https://myapp.com?rsvp=[insert rsvp here]. Does it matter if the hacker intercepts the RSVP using the redirection hack but does not have valid a ticket object belonging to the application or the application's Hawk credentials?

Advanced scoping

@hueniverse I'm aware this may be somewhat outside the scope of Oz directly but posting here because I've had these issues with OAuth 2.0 at the company I work for and would like to have at least a little discussion will others that are implementing services with the expectation of both outside integration and internal use.

Originally I had implemented an OAuth 2.0 server in Node.js with some custom additions to it (RSA pub/priv key verification, encryption, etc) because the server granting tokens was not also serving up the data / resources. So because this is already something a third party can't implement with any existing OAuth 2 client we decided any third parties will have to implemented something custom which opens up the door for us to explore a bit.

With these additions the implementation would have worked for a couple use cases but really became unwieldy. As it included more and more resources and user types (I'll explain further down) it just became very clear it was not going to work in the long term.

Our use case is somewhat complicated but I have to imagine others in the open source world encounter issues like this as well.

Given resources X, Y, Z which all have sub-resources such as X.profile, X.orderHistory, etc we were looking at ways for user type X, Y, and Z all to login (separate services, single authentication system). To clarify without going into too much detail imagine X as customers, Y as sales reps / resellers, and Z as employees.

X should be able to login directly and view their profile and orderHistory. Simple enough: [ 'x:profile', 'x:order_history' ]

Y should be able to login as a sales person and view their profile but also details on customers they brought in (this is where it gets complicated). [ 'y:profile', 'y:x:profile', 'y:x:orderHistory' ] ?

This is the problem that I would have to imagine others have faced. I'd be up for writing some sort of validation library that could be used along with Oz but I wanted to sort of throw this out there to see if it was a problem others have seen.

Unfortunately we (the development team at my office) recently took to looking at Amazon's implementation of authentication statements and policies for describing resources but it seems to be far more than we need.

Feel free to close of course if this is something you would rather not even discuss here but if you have any idea where a good forum for this might be I would greatly appreciate directions on where to take this.

Thanks.

Edit: here is a link to the Amazon statements I referred to: http://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies-basic-structure

Delegated Authentication

Curious if there's support for delegated identity authentication (e.g. OpenID Connect + OAuth2) or it's currently only purely an access authorization scheme.

Tooling and Examples

First off, this is awesome!

As someone that also detests Oauth2, like seriously, I am really happy that we might have a credible way past Oauth2. Hot stuff.

So i have used Hawk Auth before and while I loved it my biggest stumbling point was not being able to use a decent REST client that handled the auth. Do you know of any REST clients that support this new protocol? Alternatively how did you get around this if not? I know unit tests and integration tests go a long way to remove the need for a lot of manual tests but sometimes it is still necessary.

Secondly, can you point me in the direction of implementation examples? I believe hueniverse/postmile is one, though I haven't dug into the code yet. Any others?

Support multiple host names in hostHeader option in request parsing

X-Forwarded-Host HTTP headers can contain a comma separated list of header names in the case of multiple forwards. The description of the options object in oz/lib/request.js suggest you can simply pass the header value. The corresponding regex however, does not match multiple comma separated host names.

/*
var options = {
    hostHeader: X-Forwarded-Host,           // Alternative host header modified by proxies
    isHttps: false                          // Used to determine default port if not present in Host header, defaults to false
};
*/

Why is ticket key a hex of a base64Url random string?

Looking at lib/ticket.js it appears that the random string generated by Cryptiles.randomString is hex-ed to produce the ticket key.

However, Cryptiles.randomString already produces a base64Url encoded string.

Is this a slip or is there a reason for doing this that I am not getting?

Jan

2-Legged Workflow

From what I understand the workflow described in the README is a 3-legged workflow (when there is a third-party involved). To create a 2-legged workflow, is it safe to skip the grant and rsvp steps of the workflow described in the README? The biggest issue I see with a 2-legged workflow is revoking a ticket (or grant).

SIDE NOTE: For those who do not know about or understand the 2-legged, 3-legged, or n-legged workflows, check out http://hueniverse.com/oauth/guide/terminology/

Validate app credentials before issuing access delegation tickets

I have a question about delegating access to other applications.

From my understanding, if App A wants to delegate access to App B, it will request a new ticket from the 'reissue'-endpoint, stating that it should be issued to App B. App A will then transfer this ticket to App B.

Now when App B starts making requests using the ticket, its App credentials were never actually verified. In other words: It is up to App A to verify the identity of App B when it transfers the delegated access ticket. If it fails to do so, anyone could make requests in the name of App B.

Wouldn't it make sense to have an rsvp-like workflow instead? App A would only request an 'access delegation'-rsvp instead of the actual ticket, which it then transfers to what it assumes is App B. To get the actual ticket from the rsvp, App B would have to obtain an app token first. Now App B could even prove its identity to App A by responding with some key stored in the original token (e.g. in ext.public).

Grant Object Creation

When and how is the grant object supposed to be created. Is it derived from the user's username and password?

Confirming understanding of Oz workflow

I want to confirm that I understand the Oz workflow correctly after reading the README and the code. Are the following (more detailed) steps describing the Oz workflow (without delegation) correct?

  1. (Before the workflow starts) The application is registered with the server and is assigned Hawk credentials, which include an application ID and a randomly-generated key.
    • NOTE: The method in which this is done is not part of the Oz protocol
  2. Application: Make POST /oz/app request to Server (Oz.endpoints.app())
    • Send Hawk credentials or an app object (Hawk credentials with scope and delegate)
    • Get application ticket in return
    • NOTE: This step allows the application to manage its own resources on the Server
  3. Application: Make POST /oz/reissue request to Server (Oz.endpoints.reissue())
    • Send the scope array (optional) and the application ticket ID (as an Hawk authenticated requested using the application ticket)
    • Get new application ticket in return
    • NOTES
      • Keeps the application ticket fresh
      • May not be necessary, especially if the application just obtained the ticket
  4. Application: Direct user to the server (possibly by redirecting)
    • Sends the scope, application ticket ID, and (possibly) callback URL (URL back to app)
    • NOTE: The method in which this is done is not part of the Oz protocol
  5. User: Log in to the server
    • NOTE: The method in which this is done is not part of the Oz protocol
  6. Server: Display scope (sent by the application in Step 2) and prompt user to approve the scope
    • NOTE: The method in which this is done is not part of the Oz protocol
  7. User: Approve scope
    • NOTE: The method in which this is done is not part of the Oz protocol
  8. Server: Receive approval from user
    • NOTE: The method in which this is done is not part of the Oz protocol
  9. Server: Generate RSVP
    • Get application ID (extracted from the ticket the application used to authenticate)
    • Create grant object
    • Create RSVP using application ID and grant ID (an iron-sealed string)
  10. User: Receive RSVP from server
    • NOTE: The method in which this is done is not part of the Oz protocol
  11. User: Give RSVP to application
    • NOTE: The method in which this is done is not part of the Oz protocol
    • If the application received the RSVP from the server on behalf of the user (by redirecting back to the application), then Step 9 is not necessary.
  12. Application: Make POST /oz/rsvp request to Server (Oz.endpoints.rsvp())
    • Send RSVP
    • Get user ticket in return
  13. Application: Can now use the user ticket to access user resources
  14. Application: If the user ticket expires while the user grant has not expired, renew the ticket by making a POST /oz/reissue request to the Server.

Progress feedback

I've been passively watching this project since you've started it, since there are no docs (that I'm aware of), I would kindly ask a few questions:

  • who implemented it by now? (wallmart?)
  • the progress was as you expected?
  • the overall concept was a good or you have a new idea?
  • is there be a beta version + docs planned?
  • can we (watchers) write docs and ask for feedback where we don't understand parts of the code?

Is this project dead?

Kong/kong#511

We are currently using oz as the security solution in our framework as we felt it offers the strongest security solution. We are looking to now implement a technology like Kong - which supports OAuth2. There was talk about integrating Oz into Kong but it appears this did not happen mainly because there was no complete spec for Oz -see link above. We could potentially write a Kong plug-in for Oz - however no one wants an unsupported propriety security technology as part of their architecture.

Is there an intention to complete the Oz spec? Is there any desire to have Oz integrated with frameworks such as Kong? Is there a roadmap for this project?

Securing app secret on client

An app secret is used to sing requests to server. Once app secret is exposed, a third party can use it to perform requests on behalf of another app.

I've read your post about Twitter revoking exposed secrets and got your idea:

If Twitter uses the client secret in installed application for anything other than gathering statistics, well, they should reconsider. But it’s not like they have other alternative.

As far as I understand you, that's fine that an app secret is exposed (it's really not hard to do for mobile apps, for example) as long as server is built with an assumption that that can happen.

Anything changed since 2010? Does Oz addresses the issue in any way? Or it's still better to go proxy way and keep the secret in there?

Example app?

Hi Eran,

I came across your project while investigating bearer tokens and am convinced I should be using Oz to secure my microservice, but I have no idea how to integrate it. Is there an example app I could look at for pointers?

lummox and oz

So recently I have been trying to solve a similar problem to your attempt with Oz, ie:

Making a secure but flexible authorization protocol between applications and some kind of grant / scope server.

So i came up with lummox. It differs from Oz in the following ways:

  • It is designed as a highly configurable user management, authentication and authorization service for distributed systems; it deals with user's CRUD and authentication.
  • Once authenticated, a user generates a JSON web token with an embedded scope claim (the user's scope). This scope claim is used to authorize the user for other systems. See full authentication/authorization workflow.
  • It does not deal with secure storage of this token.
  • It does not deal with securing the transport layer.

While I like the simplicity of just dealing with JSON web tokens, a well known standard, i am concerned about the lack of layers of security in my solution.

So I could implement Oz as lummox authorization protocol, keeping the user management and authentication components.

Would love to know whether people think this would be a good idea? Do you see potnential security concerns with this kind of solution?

The code is 100% unit tested so should make changing it's functionality manageable.

Requesting user authorization

Looking over the sideway client, I think I've got a reasonably working implementation of Oz using the available endpoints (/app, /reissue, /rsvp).

The one thing that I'm unclear of is how an app obtains a ticket that has been authorized by the user.

Here's my best guess:

  1. App calls /app (with credentials) to get an app ticket (with optional requested scope?)
  2. App sends app ticket to Oz authorization server for user approval
  3. Oz authorization server conducts dialog with user to grant access
  4. Oz authorization server issues rsvp ticket to app
  5. Application exchanges rsvp ticket, at /rsvp, for an authorized user ticket.

Questions:

On 1, is the app ticket intended to be used as a temporary "request token" (ala OAuth 1.0), or should something else be used? How do 2 and 4 work? Is it intended to be redirect based, and if so, what are the requirements of the client in order to indicate the redirect URIs?

Excellent work on this!

Hawk and Oz

Hey this seems really cool.

In your documentation regarding Hawk, you said Hawk addresses two legged client to server authentication while Oz is for three legged.

Is it possible to use both at the same time? Will there be any conflicts. I noticed that Oz doesn't have much documentation unlike Hawk, and hawk already has implementations in other languages too.

What are the advantages of Oz to Oauth2?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.