Assemble your own OpenID Connect identity provider with NimbusDS components

OpenID Connect IdPPractical digital identity has to be simple and reliable, yet also extensible and flexible to span various applications and contexts. Organisations differ, and so do the ways in which they authenticate users, attribute authorisations to them and then consume the resulting identity data. With that understanding in mind we figured out that a one-size-fits-all OpenID Connect IdP solution will do poorly in practice, when concrete customer needs have to be faced.

Go minimal or fully customised – the choice is yours

The OpenID Connect solution of NimbusDS was designed to make it easy for customers to become an IdP for their employees or subscribers, then customise it where they see fit:

  • Fully customisable login, consent and authorisation management pages. You can stick with the default login pages, or you can design your own to suit the appearance of your company identity or customise the user experience in the browser / mobile device. Moreover, the UI pages can be hosted on any server, at any URL, written in any language such Java/JSP, PHP, RoR, etc.
  • Pluggable authentication. NimbusDS supports username / password authentication out of the box, based on our existing AuthService software. You can replace it by your own authentication mechanisms, or add additional factors such as biometrics or token devices to achieve 2FA.
  • User sessions. The user sessions with the OpenID Connect IdP can be configured to match your policies for session duration, idle time and maximum number of associated browsers / devices.
  • Support additional scopes for other OAuth 2.0 applications. The access token issued by the OpenID Connect Server can be furnished with additional scopes, beyond the standard ones, to grant users access to other protected resources, and not just the OIDC UserInfo endpoint. The scopes attached to the token can be explicitly or implicitly consented to, based on your user / application / other policy.
  • Include custom claims in the ID Token: The ID token issued by OpenID Connect can be set to include additional arbitrary claims, such as details of the authentication event (IP address, geolocation) and user attributes.

Identity provision based on a array of simple web services

How is this level of customisation achieved? By a server back-end that is not monolithic, but based on a array of nimble RESTful /  JSON-RPC 2.0 web services, where each service caters for a specific, tightly defined task. The various tasks then put together make up the overall IdP process:

  • A web API for decoding and encoding the OAuth 2.0 / OpenID Connect protocol requests and responses exchanged with relying parties (RP). This API is used for example by the UI page for the OIDC authorisation endpoint, to render the consent form and specify which claims / scopes the user should explicitly agree on and which will be implicitly set by the IdP, based on a policy.
  • A web service for authenticating users, such as Nimbus AuthService that handles MS-AD / LDAP based authentication. Its web API is addressed by the UI pages that direct the login flow.
  • A web service for tracking the user sessions, such as NimbusSSO. It handles session creation, update, expiration and removal events. Its web API can be scripted to monitor which users are currently online and their associated browsers / devices as well.
  • An OAuth 2.0 authorisation store, which keeps track of all issued authorisation codes, access and refresh tokens. It provides a RESTful API to allow for token revocation and monitoring token usage by applications.
  • An OAuth 2.0 client registry, which contains the details and credentials / RSA / EC keys of all applications, manually or dynamically registered.
  • A user store, based on a directory, accessed either directly via LDAPv3 or via Json2Ldap.

Example: Extending OAuth 2.0 authorisations with additional scope values

The following example illustrates how an identity provider may add additional scope values to a user’s authorisation (represented by the OAuth 2.0 access token, typically of type Bear). Apart from providing single sign-on based on OpenID Connect, the IdP server may also be used as a generic OAuth 2.0 server, to grant fine-grained access to the application or access to third-party services and applications.

  • A user from the accounting department who logs in with OpenID Connect to the payroll application may be granted access to specific payment APIs.
  • A user from the IT support department who logs in with OpenID Connect to an admin dashboard app may be granted access to specific server management APIs.
  • A user from the legal department who logs in with OpenID Connect to a documentation system may be granted access to specific confidential documents.

In the context of OpenID Connect the access token is used to give the application access to the user’s profile details at the UserInfo endpoint. The scope of the access token can however be extended to grant access to additional protected resources, by including values that are recognised by these resources.

OAuth 2.0 scope for pure OpenID use only:

openid profile email

OAuth 2.0 scope with additional values recognised by other applications:

openid profile email payroll:disburse payroll:settle

The access scope that is granted to a particular user is determined during the OAuth 2.0 / OpenID Connect authorisation step. The scope to grant can be determined by explicit consent and / or by looking up the user’s and the client application’s attributes (e.g. user membership of an LDAP group, application trust level).

The additional scope values can be determined by calling an arbitrary script or executable code, which when completed should return a JSON array with the granted scope values. For example:

["openid", "profile", "email", "payroll:disburse", "payroll:settle"]

The scope is then used to compose the final OAuth 2.0 / OpenID Connect authorisation, which is passed to the OIDC server as a JSON object via a RESTful HTTP POST:

POST /authorize/67ee5264-26ff-45cd-a876-5de22fbb99b1 HTTP/1.1 
Host: oidc.wonderland.net 
Content-Type: application/json
{ 
 "sub"      : "alice@wonderland.net",
 "ACR"      : ["3"],
 "authTime" : 2147483647,
 "scope"    : ["openid", "profile", "email", 
               "payroll:disburse", "payroll:settle"],
 "userInfo" : ["sub", "name", "given_name", "family_name",
               "profile", "email", "email_verified", "locale"]
}

Upon received the authorisation, the OIDC server generates the required authorisation code (if we have a code flow) and then a matching access / refresh token pair for the authorisation.

The application can validate the access token and get its matching authorisation by making a RESTful query to the OIDC server. We also consider adding support for access tokens which include the authorisation in a JWS-signed / JWE-encrypted form, to save the need for doing lookup over the network.

The following presentation slides also give a nice overview of how the OpenID Connect IdP solution is built and how its various web service components interact with each other:
Nimbus OIDC server presentation

Nimbus JOSE+JWT 2.15.1: Quicker loading of RSA encrypters

Nimbus JOSE+JWT 2.15.1 is a maintenance release of the Java library for signing and encrypting JSON Web Tokens (JWTs) and other payloads.

What’s in it?

  • Instantiation of RSAEncrypter and DirectEncrypter objects will now happen a lot faster. There is no further need to reuse these encrypter objects in order to maintain performance. Should you wish, you can now create a new encrypter object for each JWE message that needs to be produced, with virtually no performance penalty. This was achieved by making the SecureRandom PRNG for outputting IVs a static class member. The initial seeding of the PRNG is typically a time consuming process to guarantee sufficient entropy (we measured up to 1+ second for that in tests), so the logical solution was to move the seeding procedure out of the encrypter constructors. Thanks to Dr. Michael Scott from CertiVox and Juraj Somorovsky from Uni Bochum for checking that IV security was preserved while this was done.
  • You can now pass shared secrets encoded as UTF-8 strings to the MACSigner and MACVerifier.
  • The Base64URL class was refactored to extend the general Base64 class, which made the overall code leaner and simpler to maintain.

The library JAR is distributed via Maven Central. You can also get it from the download section of the Git repo for the JOSE+JWT library.

Nimbus JOSE+JWT updated to draft suite 10

The Nimbus library for processing JWS/JWE/JWK/JWT objects in Java was updated to comply with the latest draft suite v10 released by the JOSE WG:

An important change is the new method for authenticated AES/CBC encryption based on draft-mcgrew-aead-aes-cbc-hmac-sha2-01 – Authenticated Encryption with AES-CBC and HMAC-SHA. This replaced the previously used method based on a concatenating KDF.

Other changes include the introduction of an “crit” header parameter to designate custom JWS/JWE headers that shouldn’t be ignored by clients, also several changes in terminology and a change in AAD computation for AES/GCM to allow multiple recipients. The complete change log can be found in the draft document histories and the respective CHANGELOG file in the library package.

The new library version should appear in Maven Central within a few hours.

Thanks to everyone who contributed, also to our colleagues on the JOSE WG who continue work on refining the specs.

JWS and JWE to secure tokens, messages and channels

Hard work pays off. The positive and encouraging feedback that we started receiving from early adopters of Nimbus JOSE + JWT for Java was a great inspiration and at same time motivation to continue refinement of the library.

Developers cited the new JSON-based formats for message signing and encryption, JWS and JWE, being a significant improvement in terms of simplicity and programming, particularly in comparison with the existing XML digital signature standard. A lot of effort was put to ensure this simplicity was also carried in the library, by making its application facing calls and class structures as simple and intuitive as possible. The same approach was applied to the API for plugging crypto algorithms in, which should make tracking draft changes to JOSE algorithms easier too.

Our main intended use of JWS/JWE/JWT is for generating and processing tokens in OpenID Connect. Last week we found a nice use case for JWE to protect identity data that is exchanged between Nimbus AuthService agents and the SaaS apps of customers. Other users have reported success in using JWS/JWE to exchange patient records between hospitals, sign transactions and encrypt message channels between web services.

Huge thanks to the JOSE WG for crafting this specification as well as to all developers who contributed to the library and continue to do so.

 

Direct JWE encryption

Release 2.14 of the Nimbus JOSE + JWT library adds support for direct JWE encryption using shared symmetric keys. Our particular use case for that is to secure synchronisation of identity data between an on-premise user authentication agent and an OpenID Connect provider service that we’re currently developing.

Direct JWE encryption comes in handy when you have control over both communication endpoints and wish to save the overhead of issuing public / private key pairs, such as RSA, and then wrapping / unwrapping them for the actual encryption / decryption.

Direct encryption is represented by setting the algorithm (alg) header parameter to “dir” and then specifying the actual encryption method to apply on the plain text, e.g. 128-bit AES/GCM:

{ "alg":"dir", "enc":"A128GCM" }

Programmaticaly you can create the header like this:

import com.nimbusds.jose.*;
JWEHeader header = new JWEHeader(JWEAlgorithm.DIR, EncryptionMethod.A128GCM);

You can then complete the JWE object construction:

JWEObject jweObj = new JWEObject(header, new Payload("Hello world!"));

To encrypt the JWE object you need a key with the matching length for A128GCM encryption, that is 128 bits or 16 bytes. The key must be shared between sender and recipient and kept secret, of course.

import com.nimbusds.jose.crypto.*;

byte[16] key = { ... };
DirectEncrypter encrypter = new DirectEncrypter(key);

// You can now use the encrypter on one or more JWE objects 
// that you wish to secure
jweObject.encrypt(encrypter);
String jweString = jweObject.serialize();

The resulting JWE object string will then look similar to this:

eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4R0NNIn0..0CxTyOgMw0nsG-KS.BJkGEk8LW3qOOU6v.dkNwv-fbQOgoOuYr6Kg74g

Notice that the encrypted key part (the second part) of the JWE string is missing. RSA and ECC encryption will have it, but direct encryption not.

To decrypt the JWE string on the other end you need the same symmetric key.

jweObject = JWEObject.parse(jweString);
JWEDecrypter decrypter = new DirectDecrypter(key);
jweObject.decrypt(decrypter);

// Prints "Hello world!"
System.out.println(jweObject.getPayload());

The Nimbus JOSE+JWT library supports all standard encryption methods for direct JWE:

  • A128CBC+HS256 – requires 256 bit symmetric key
  • A256CBC+HS512 – requires 512 bit symmetric key
  • A128GCM – requires 128 bit symmetric key
  • A256GCM – requires 256 bit symmetric key

Nimbus JOSE+JWT 2.13.1 maintenance release

We just released a maintenance release of the Java library for creating and processing plain, JWS and JWE objects and JSON Web Tokens (JWTs).

The new release fixes a JWT time unit representation bug that used milliseconds instead of seconds for the exp, nbf and iat claims.

It also ensures that Header.toBase64() returns the original parsed string for JOSE objects that are being processed. This bug was causing false HMAC integrity check rejections in situations where the sending and the receiving system produce JSON headers with different serialisations.

Thanks to Jochem Berndsen and to Wisgary Torres from the Microsoft XBox team for reporting these issues.

The new release should become available on Maven Central within a few hours.

RSA encryption added to the Nimbus JOSE + JWT library

The new 2.13 release of the Java library for Javascript Object Signing and Encryption (JOSE) and JSON Web Tokens (JWT) adds support for RSA encryption. You can now create encrypted payloads and tokens with RSAES-PKCS1-V1_5 and  RSAES-OAEP, using the authenticated AES/CBC+HMAC and AES/GCM encryption methods.

The following example demonstrates the typical lifecycle of an encrypted JWT, secured with RSA-OAEP and 128-bit AES/GCM.

// Compose the JWT claims set
JWTClaimsSet jwtClaims = new JWTClaimsSet();
jwtClaims.setIssuer("https://openid.net");
jwtClaims.setSubject("alice");
List<String> aud = new ArrayList<String>();
aud.add("https://app-one.com");
aud.add("https://app-two.com");
jwtClaims.setAudience(aud);
// Set expiration in 10 minutes
jwtClaims.setExpirationTime(new Date(new Date().getTime() + 1000*60*10));
jwtClaims.setNotBeforeTime(new Date());
jwtClaims.setIssueTime(new Date());
jwtClaims.setJWTID(UUID.randomUUID().toString());

System.out.println(jwtClaims.toJSONObject());
// Produces 
// { 
//   "iss" : "https:\/\/openid.net",
//   "sub" : "alice",
//   "aud" : [ "https:\/\/app-one.com" , "https:\/\/app-two.com" ],
//   "exp" : 1364293137871,
//   "nbf" : 1364292537871,
//   "iat" : 1364292537871,
//   "jti" : "165a7bab-de06-4695-a2dd-9d8d6b40e443"
// }

// Request JWT encrypted with RSA-OAEP and 128-bit AES/GCM
JWEHeader header = new JWEHeader(JWEAlgorithm.RSA_OAEP, EncryptionMethod.A128GCM);

// Create the encrypted JWT object
EncryptedJWT jwt = new EncryptedJWT(header, jwtClaims);

// Create an encrypter with the specified public RSA key
RSAEncrypter encrypter = new RSAEncrypter(publicKey);

// Do the actual encryption
jwt.encrypt(encrypter);

// Serialise to JWT compact form
String jwtString = jwt.serialize();

System.out.println(jwtString);
// Produces 
//
// eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExMjhHQ00ifQ.K52jFwAQJH-
// DxMhtaq7sg5tMuot_mT5dm1DR_01wj6ZUQQhJFO02vPI44W5nDjC5C_v4p
// W1UiJa3cwb5y2Rd9kSvb0ZxAqGX9c4Z4zouRU57729ML3V05UArUhck9Zv
// ssfkDW1VclingL8LfagRUs2z95UkwhiZyaKpmrgqpKX8azQFGNLBvEjXnx
// -xoDFZIYwHOno290HOpig3aUsDxhsioweiXbeLXxLeRsivaLwUWRUZfHRC
// _HGAo8KSF4gQZmeJtRgai5mz6qgbVkg7jPQyZFtM5_ul0UKHE2y0AtWm8I
// zDE_rbAV14OCRZJ6n38X5urVFFE5sdphdGsNlA.gjI_RIFWZXJwaO9R.oa
// E5a-z0N1MW9FBkhKeKeFa5e7hxVXOuANZsNmBYYT8G_xlXkMD0nz4fIaGt
// uWd3t9Xp-kufvvfD-xOnAs2SBX_Y1kYGPto4mibBjIrXQEjDsKyKwndxzr
// utN9csmFwqWhx1sLHMpJkgsnfLTi9yWBPKH5Krx23IhoDGoSfqOquuhxn0
// y0WkuqH1R3z-fluUs6sxx9qx6NFVS1NRQ-LVn9sWT5yx8m9AQ_ng8MBWz2
// BfBTV0tjliV74ogNDikNXTAkD9rsWFV0IX4IpA.sOLijuVySaKI-FYUaBy
// wpg

// Parse back
jwt = EncryptedJWT.parse(jwtString);

// Create a decrypter with the specified private RSA key
RSADecrypter decrypter = new RSADecrypter(privateKey);

// Decrypt
jwt.decrypt(decrypter);

// Retrieve JWT claims
System.out.println(jwt.getJWTClaimsSet().getIssuer());;
System.out.println(jwt.getJWTClaimsSet().getSubject());
System.out.println(jwt.getJWTClaimsSet().getAudience().size());
System.out.println(jwt.getJWTClaimsSet().getExpirationTime());
System.out.println(jwt.getJWTClaimsSet().getNotBeforeTime());
System.out.println(jwt.getJWTClaimsSet().getIssueTime());
System.out.println(jwt.getJWTClaimsSet().getJWTID());

Check out src/test/java/com/nimbusds/jwt/EncryptedJWTTest.java for the complete code.

Don’t forget that the library JavaDocs are your friend. They include full description of all classes and methods, references to the applicable JOSE and other spec sections as well as short code snippets.

Thanks for Axel Nennker, David Ortiz and Juraj Somorovsky from the JOSE community who contributed with concrete code and suggestions.

Note that the current A128CBC+HS256 and A256CBC+HS512
specifications may get revised by the JOSE WG to switch to draft-mcgrew-aead-aes-cbc-hmac-sha2-01 for appending authenticated encryption to AES/CBC.

Json2Ldap adds directory server fail-over and load-balancing

masthead-json2ldapThe new year began with the third major release of Json2Ldap, the established middleware for web-friendly JSON-RPC access to directory servers such as MS Active Directory, OpenLDAP and OpenDJ.

This is a summary of what’s in the new 3.0 version.

Directory server fail-over and load-balancing

Resilience and scalability is a common requirement in enterprise and SaaS applications. You can now configure Json2Ldap to fail-over between two or more directory servers, or alternatively, to perform round-robin directory server selection.

Fail-over is a common strategy to provide backup in case your primary LDAP server fails. To handle such situations you can specify a secondary, tertiary, and so on servers for Json2Ldap to connect to if the primary becomes unavailable.

To configure fail-over:

json2ldap.defaultLDAPServer.selectionAlgorithm = FAILOVER
json2ldap.defaultLDAPServer.url = ldap://192.168.1.10 ldap://192.168.1.20
json2ldap.defaultLDAPServer.connectTimeout = 500

The above configuration will set a secondary LDAP server on IP 192.168.1.20. Json2Ldap will direct new ldap.connect requests to it if it’s not able to connect to the primary server within 500 milliseconds.

Round-robin is the alternative server selection method. It provides for load-balancing between multiple servers and is also a form of fail-over in case one or more of the servers in the set become unavailable.

To configure round-robin selection with two servers, using again a connect time-out of 500ms:

json2ldap.defaultLDAPServer.selectionAlgorithm = ROUND-ROBIN
json2ldap.defaultLDAPServer.url = ldap://192.168.1.10 ldap://192.168.1.20
json2ldap.defaultLDAPServer.connectTimeout = 500

You can find out more about configuring fail-over and round-robin operation in the Json2Ldap docs on specifying the default LDAP server.

Support for Virtual-List-View searches

The Virtual-List-View (VLV) control (draft-ietf-ldapext-ldapv3-vlv-09) allows web clients to retrieve an arbitrary subset of an LDAP search result. You can think of it as a sophisticated makeover of the Simple Paged Results (RFC 2696) control. The VLV control allows you to specify an offset into the result set and a number of entries to get before and after the offset position. This can for instance be of great help in devising efficient browsing web UIs when the result sets are expected to be huge.

To apply VLV to an ldap.search request add a parameter like this:

"vlv" : { "offset":50, "after":24 }

This will ask to return 25 entries at offset fifty. Note that the VLV control also requires the presence of a sort control in order to determine the entry order, e.g.:

"sort" : { "key":"givenName" }

I have put together a list of the directory servers that support Virtual-List-View. A brief look at the list will show you that it’s widely supported. You may however have to create specific indexes in your directory to enable it. Check you server documentation for that.

Use of the VLV control in Json2Ldap is detailed in the ldap.search API docs.

Normalising attribute names

The attribute names that Json2Ldap returns with ldap.getEntry, ldap.search and ldap.getRootDSE appear as defined in the directory schema. However, if you don’t have prior knowledge of their letter-case retrieving them from the result JSON object can be a bit of a problem.

var givenName = result["givenName"];

The solution to this has been to normalise all names, e.g. converting them to lower-case, before processing the result.

Json2Ldap 3.0 added a new optional parameter “normalize” to solve this problem. With it all attribute names in the result will be normalised, or converted to lower-case. So you don’t have to worry about the extra conversion. It will be done for you, quite efficiently, inside Json2Ldap.

Retrieving subordinate subtree entries

The ldap.search SUBORDINATE_SUBTREE scope parameter has been renamed to SUBORDINATES. This is the only breaking change in the Json2Ldap web API and was done to make the parameter compatible with the LDAP URL schema.

API keys

You can now also specify API keys to ensure only selected web clients can access the web API of Json2Ldap. These are passed as an optional “apiKey” parameter to each web call. You can define API keys for global access as well as keys that are only for certain API calls. Check out the API key configuration to find out more.

The classic X.509 client certificate access controls are still supported.

Simplified configuration files

Json2Ldap 3.0 moved the configuration parameters from the web.xml file to a set of simpler text properties files that continue to follow the established semantics. Many of the configuration properties were also given better and more intuitive names. As a result the whole task of configuring Json2Ldap should have become easier and less error-prone (by switching from XML to simple key / value properties). Adding a web UI configuration editor is on the roadmap for 2013 / 2014.

Ready to try out Json2Ldap 3.0?

You can get a copy of Json2Ldap 3.0 for evaluation from the download section. Existing subscribers should have already been notified and received their download links for the full version.

You’re welcome to get in touch with us if you have questions about the new version or feedback to share.

 

 

The full 3.0 change log is on the Json2Ldap spec page.

 

Nimbus JOSE + JWT 2.10 is on Maven Central now

The latest stable release of the Java library for handling JOSE + JWT messages is now available on Maven Central.

http://search.maven.org/#browse|537656995

Thanks to Justin Richer from MITRE for taking care of all necessary work to package and submit the library to the repo.

Earlier this month the library was updated to the latest -08  draft suite of JOSE as well as JWT -06. We’re still looking for a Java developer to contribute support for the standard JWE algorithms. Signature support for the standard HMAC, RSASSA and ECDSA algorithms has been fully available since the first release.

The library Git repo is at https://bitbucket.org/nimbusds/nimbus-jose-jwt/

The sources come with ample documentation and include useful examples:

http://nimbusds.com/files/jose-jwt/javadoc

 

Nimbus JOSE + JWT 2.9

I just released a new version of the Java library for handling Javascript Object Signing and Encryption (JOSE) as well as JSON Web Tokens (JWTs).

The library Git repo: https://bitbucket.org/nimbusds/nimbus-jose-jwt/

The JavaDocs: http://nimbusds.com/files/jose-jwt/javadoc/

This new version incorporates all small changes that came with the latest JOSE -08 draft suite and the JWT -06 draft.

I’m still looking for a contributor to help out with the JWE algorithm implementation. All standard JWS algorithms have been implemented.

Mike Jones from the JOSE working group released a new draft from specifying private and symmetric JSON Web Keys (JWKs). This looks like a useful development and I intend to add support for private keys in a future version of the library.

You can read the JPSK spec at

http://tools.ietf.org/html/draft-jones-jose-json-private-and-symmetric-key-00

 

 

NimbusSSO 2.7

Highlights of December’s NimbusSSO 2.7 release:

Compound session keys for better performance

We reworked the session store architecture so that explicit transactions (JTA) are no longer required. Instead, we now use compound keys, a technique commonly used in NoSQL, which results in quicker performance for common session operations. As a side effect, file system access is no longer required for transaction persistance, which makes NimbusSSO setup and administration a whole lot easier.

More detailed error messages

We upgraded the underlying JSON-RPC 2.0 Base library which in its latest 1.30 release provides for more detailed error messages. This will aid developing client-side code against the NimbusSSO JSON API.

For example, instead of a returning a generic “Invalid parameters” on a missing or badly typed JSON parameter, NimbusSSO will now include a brief description of the cause:

Response [error]: -32602, Invalid parameters: Missing SID parameter(s)

This is the last planned release of NimbusSSO for 2012. To see what’s intended for next year, check our 2013 roadmap.

Nimbus JOSE + JWT 2.5 updates JWK format

The Java library for JSON web signatures and encryption (JOSE) received a tiny update to reflect the latest changes to the -07 set of IEFT drafts. These were mostly related to the format of the JSON structure for representing public RSA keys.

Example:

{ 
   "alg" : "RSA",
   "n"   : "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx
           4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMs
           tn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2
           QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbI
           SD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqb
           w0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
   "e"   : "AQAB",
   "kid" : "2011-04-29"}
 }

You can download the Nimbus JOSE + JWT library source and JAR from the project Git repo at

https://bitbucket.org/nimbusds/nimbus-jose-jwt

Nimbus JOSE + JWT 2.4 with Maven support

Thanks to a contribution from Ville Kurkinen the Java library for handling JWS/JWE protected messages and JSON Web Tokens (JWT) has now Maven support.

You can download the library sources and compiled JAR from the project Git repo:

https://bitbucket.org/nimbusds/nimbus-jose-jwt/

The library supports all standard JSON Web Signature (JWS) algorithms based on HMAC encoding, RSA public/private keys and Elliptic Curve cryptography. See the Nimbus JOSE+JWT wiki for examples.

 

Nimbus JOSE + JWT 2.3 with improved thread-safety

I just released another update to the Java library for processing JSON Web Signature (JWS), JSON Web Encryption (JWE), JSON Web Key (JWK) and JSON Web Token (JWT) objects.

A goal of this 2.3 release was to improve the thread-safety of the key classes to allow seamless use in concurrent server environments.

The core classes for representing the JOSE objects – PlainObject, JWSObject and JWEObject – are all thread-safe now. So are the implemented standard HMAC, RSA and ECDSA signature and verification providers in the com.nimbusds.jose.crypto package.

To ease understanding of which classes are immutable and/or thread-safe, I applied the widely used JCIP concurrency annotations. The result can be seen in the comprehensive JavaDocs for the Nimbus JWT+JOSE library.

Another useful addition was the getParsedParts() and getParsedString() methods of JOSEObject to query the original Base64URL parts or entire string of a parsed JOSE object. As you may know, JOSE doesn’t apply canonicalisation to the JSON header, which may result in different serialisations across implementations and even within the same implementation, so it’s useful to have these methods when you need to get back the original parsed string.

Finally, there was yet another naming change to signature interfaces and classes. We hope we got it right this time :)

You can get the latests JAR, sources and JavaDocs of the library from its Git repo at

https://bitbucket.org/nimbusds/nimbus-jose-jwt/downloads

We also have a short wiki there to get you started.

Validate vs verify in the context of cryptography

Writing specs and libraries requires excellent command of terminology. The concepts of validation and verification occasionally get mixed up in cryptography and so I looked for a good authoritative text to clarify the two terms and their correct use.

RFC 4949Internet security glossary, version 2, turned out to provide exactly what I needed:

On the difference between validate and verify:

Usage: To ensure consistency and align with ordinary English usage, IDOCs SHOULD comply with the following two rules:

  • Rule 1: Use “validate” when referring to a process intended to establish the soundness or correctness of a construct (e.g., “certificate validation”). (See: validate.)
  • Rule 2: Use “verify” when referring to a process intended to test or prove the truth or accuracy of a fact or value (e.g., “authenticate”). (See: verify.)

Tutorial: The Internet security community sometimes uses these two terms inconsistently, especially in a PKI context. Most often,
however, we say “verify the signature” but say “validate the certificate”. That is, we “verify” atomic truths but “validate”
data structures, relationships, and systems that are composed of or depend on verified items. This usage has a basis in Latin:

The word “valid” derives from a Latin word that means “strong”. Thus, to validate means to check that a construct is sound. For
example, a certificate user validates a public-key certificate to establish trust in the binding that the certificate asserts
between an identity and a key. This can include checking various aspects of the certificate’s construction, such as verifying the
digital signature on the certificate by performing calculations, verifying that the current time is within the certificate’s
validity period, and validating a certification path involving additional certificates.

The word “verify” derives from a Latin word that means “true”. Thus, to verify means to check the truth of an assertion by
examining evidence or performing tests. For example, to verify an identity, an authentication process examines identification
information that is presented or generated. To validate a certificate, a certificate user verifies the digital signature on
the certificate by performing calculations, verifies that the current time is within the certificate’s validity period, and may
need to validate a certification path involving additional certificates.

“Verify signature” is the correct term, not validate

Deprecated Term: IDOCs SHOULD NOT use this synonym [valid signature]. This Glossary recommends saying “validate the certificate” and “verify the signature”; therefore, it would be inconsistent to say that a signature is “valid”. (See: validate, verify.)

Nimbus JOSE + JWT 2.2

The Java library for handling JSON Web Signature (JWS), JSON Web Encryption (JWE) and JSON Web Token (JWT) messages just got an update to match the latest 06 draft version of the spec suite.

The JWE code was affected most, to reflect the major change of introducing composite algorithm identifiers and moving the initialisation vector (IV) header parameter to a body part on its own. With that the average size of encrypted tokens gets noticeably smaller and even the core library code was reduced and simplified. Thanks to everyone on the JOSE WG for contributing to this improvement!

The updated Nimbus JOSE+JWT library sources, documentation and JAR are available in the project Git repo at

https://bitbucket.org/nimbusds/nimbus-jose-jwt/wiki/Home

Earlier this month the library went through a major rewrite for its 2.0 release and is now vastly improved. There are now separate classes for handling arbitrary plaintext, JWS and JWE objects alongside the original JWT use case. New nimbler interfaces were created to decouple algorithm implementations from the core protocol code. And finally, overall usability and object orientation were improved in order to make it easier to support a wider array of use cases and deployments.

 

OAuth 2.0 and Bearer are RFCs now

Good news! The OAuth 2.0 Core and Bear specifications are official RFCs now:

RFC 6749 The OAuth 2.0 Authorization Framework

RFC 6750 The OAuth 2.0 Authorization Framework: Bearer Token Usage

OAuth 2.0 tokens will be used in the upcoming NimbusSSO addons that will provide OpenID Connect IdP and IdC functionality.

Dick Hardt has a nice article looking back at the history of OAuth 2.0 and its purpose.

Thanks to everyone who contributed!

LDAP user authentication explained

LDAP user authentication is the process of validating a username and password combination against a directory server such MS Active Directory, OpenLDAP or OpenDJ. LDAP directories are standard technology for central storing of user, group and permission information and serving that to applications in the enterprise. Today, with help of Json2Ldap software, they can even be accessed from the web.

Authenticating users against an LDAP directory is a two-step process. This article explains the mechanics of it and then how to configure it in NimbusDS AuthService and NimbuSSO software.

Step 1 – Resolving the username to a directory entry attribute

User entries in a directory are identified by distinguished names (DNs) which resemble a path-like structure starting at the directory root.

uid=alice,ou=people,dc=wonderland,dc=net

In order to authenticate a user against an LDAP directory you need to obtain their DN as well as their password.

When you have a login form in your application, people typically enter a simple identifier such as their username or email address. You  don’t expect them to memorise the DN of their directory entry. This would be impractical.

To solve this issue a DN resolution procedure is used. It takes the user’s name or email, then runs a search against the name or email attributes of all user entries to find the matching entry DN. Directories employ highly efficient indexing and caching, so these searches are typically very fast.

The directory attributes to search for are defined in the searchFilter configuration parameter. The default AuthService configuration searches the users’ UID and email attributes. The %u placeholder is substituted with the user identifier entered in the login form.

authService.dnResolution.searchFilter = (|(uid=%u)(mail=%u))

If you want to search for UID only the search filter would look like this:

authService.dnResolution.searchFilter = (uid=%u)

If you want to search for UID, email and employee number, extend the filter to

authService.dnResolution.searchFilter = (|(uid=%u)(mail=%u)(employeeNumber=%u))

Two important things to observe when configuring DN resolution and creating new user entries in the directory:

  • The attributes – username, email, etc – with which users login must be unique. If two entries are found to have the same identifying attribute, e.g. email, authentication will be promptly denied.
  • Make sure every user who is expected to login has a defined attribute for the identifying attribute. For example, if users are going to login with their email address, make sure all accounts have a defined email attribute. Else authentication will fail.

NimbusDS AuthService as well as NimbusSSO do not say in authentication responses to web clients what caused a login to fail – whether a wrong username, a wrong password, or both. To troubleshoot situations where a user is not able to login despite entering a correct username and password, check the service logs. In contrast to the service responses they record the exact cause of a denied authentication request.

If a login was rejected due to a bad username, a line like this will appear in the log:

2012-10-01 10:52:51,460 INFO – user.auth: username=tom authenticated=false message=Invalid username

If the username was correctly resolved, but the password was bad:

2012-10-01 10:55:05,662 INFO – user.auth: username=alice DN=uid=alice,ou=people,dc=wonderland,dc=net authenticated=false message=Invalid password

If we have correctly resolved the user’s directory entry DN, we can proceed to the next step – checking the password.

Step 2 – Validating the user password

Passwords are checked by an LDAP command called bind. Basically, a connection is opened to the directory server, then a request is sent to authenticate the connection as a particular user entry by passing its entry DN and password.

DN: uid=alice,ou=people,dc=wonderland,dc=net
password: secret

If both values are correct, the directory server returns success. Else, it returns an LDAP error “Invalid credentials” (code 49).

Important things to note here:

  • The password is checked against an attribute in the user’s entry dedicated to serve that purpose. If you’re using a standard directory schema, this attribute is called userPassword. In MS Active Directory the name of this attribute is unicodePwd. Make sure that every user who is expected to login has a defined password attribute. Else authentication will fail.
  • The password values are often hashed and may be additionally protected, e.g. by making them write-only. Therefore a simple LDAP read and comparison will generally not work here. The bind command is always the preferred method.
  • Password are typically case sensitive.

Again, remember that log files are your friend. They record details of every login attempt and can be used for quick troubleshooting when authentication is not working as expected. If you need more help, with configuring AuthService or NimbusSSO, or even with your directory, don’t hesitate to contact us.