----------------------------------------------------------------------- -- security-oauth-jwt -- OAuth Java Web Token -- Copyright (C) 2013, 2017 Stephane Carrez -- Written by Stephane Carrez (Stephane.Carrez@gmail.com) -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. -- You may obtain a copy of the License at -- -- http://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -- See the License for the specific language governing permissions and -- limitations under the License. ----------------------------------------------------------------------- with Ada.Calendar.Conversions; with Interfaces.C; with Util.Encoders; with Util.Strings; with Util.Serialize.IO; with Util.Properties.JSON; with Util.Log.Loggers; package body Security.OAuth.JWT is Log : constant Util.Log.Loggers.Logger := Util.Log.Loggers.Create ("Security.OAuth.JWT"); function Get_Time (From : in Util.Properties.Manager; Name : in String) return Ada.Calendar.Time; -- Decode the part using base64url and parse the JSON content into the property manager. procedure Decode_Part (Into : in out Util.Properties.Manager; Name : in String; Data : in String); function Get_Time (From : in Util.Properties.Manager; Name : in String) return Ada.Calendar.Time is Value : constant String := From.Get (Name); begin return Ada.Calendar.Conversions.To_Ada_Time (Interfaces.C.long'Value (Value)); end Get_Time; -- ------------------------------ -- Get the issuer claim from the token (the "iss" claim). -- ------------------------------ function Get_Issuer (From : in Token) return String is begin return From.Claims.Get ("iss"); end Get_Issuer; -- ------------------------------ -- Get the subject claim from the token (the "sub" claim). -- ------------------------------ function Get_Subject (From : in Token) return String is begin return From.Claims.Get ("sub"); end Get_Subject; -- ------------------------------ -- Get the audience claim from the token (the "aud" claim). -- ------------------------------ function Get_Audience (From : in Token) return String is begin return From.Claims.Get ("aud"); end Get_Audience; -- ------------------------------ -- Get the expiration claim from the token (the "exp" claim). -- ------------------------------ function Get_Expiration (From : in Token) return Ada.Calendar.Time is begin return Get_Time (From.Claims, "exp"); end Get_Expiration; -- ------------------------------ -- Get the not before claim from the token (the "nbf" claim). -- ------------------------------ function Get_Not_Before (From : in Token) return Ada.Calendar.Time is begin return Get_Time (From.Claims, "nbf"); end Get_Not_Before; -- ------------------------------ -- Get the issued at claim from the token (the "iat" claim). -- ------------------------------ function Get_Issued_At (From : in Token) return Ada.Calendar.Time is begin return Get_Time (From.Claims, "iat"); end Get_Issued_At; -- ------------------------------ -- Get the authentication time claim from the token (the "auth_time" claim). -- ------------------------------ function Get_Authentication_Time (From : in Token) return Ada.Calendar.Time is begin return Get_Time (From.Claims, "auth_time"); end Get_Authentication_Time; -- ------------------------------ -- Get the JWT ID claim from the token (the "jti" claim). -- ------------------------------ function Get_JWT_ID (From : in Token) return String is begin return From.Claims.Get ("jti"); end Get_JWT_ID; -- ------------------------------ -- Get the authorized clients claim from the token (the "azp" claim). -- ------------------------------ function Get_Authorized_Presenters (From : in Token) return String is begin return From.Claims.Get ("azp"); end Get_Authorized_Presenters; -- ------------------------------ -- Get the claim with the given name from the token. -- ------------------------------ function Get_Claim (From : in Token; Name : in String; Default : in String := "") return String is begin return From.Claims.Get (Name, Default); end Get_Claim; -- ------------------------------ -- Decode the part using base64url and parse the JSON content into the property manager. -- ------------------------------ procedure Decode_Part (Into : in out Util.Properties.Manager; Name : in String; Data : in String) is Decoder : constant Util.Encoders.Decoder := Util.Encoders.Create (Util.Encoders.BASE_64_URL); Content : constant String := Decoder.Decode (Data); begin Log.Debug ("Decoding {0}: {1}", Name, Content); Util.Properties.JSON.Parse_JSON (Into, Content); end Decode_Part; -- ------------------------------ -- Decode a string representing an encoded JWT token according to the JWT specification: -- -- Section 7. Rules for Creating and Validating a JWT -- -- The JWT token is composed of 3 parts encoded in Base64url and separated by '.' . -- The first part represents the header, the second part the claims and the last part -- the signature. The Decode operation splits the parts, decodes them, -- parses the JSON content represented by the header and the claims. -- The Decode operation does not verify the signature (yet!). -- -- Return the decoded token or raise an exception. -- ------------------------------ function Decode (Content : in String) return Token is Pos1 : constant Natural := Util.Strings.Index (Content, '.'); Pos2 : Natural; Result : Token; begin if Pos1 = 0 then Log.Error ("Invalid JWT token: missing '.' separator. JWT: {0}", Content); raise Invalid_Token with "Missing header separator"; end if; Pos2 := Util.Strings.Index (Content, '.', Pos1 + 1); if Pos2 = 0 then Log.Error ("Invalid JWT token: missing second '.' separator. JWT: {0}", Content); raise Invalid_Token with "Missing signature separator"; end if; Decode_Part (Result.Header, "header", Content (Content'First .. Pos1 - 1)); Decode_Part (Result.Claims, "claims", Content (Pos1 + 1 .. Pos2 - 1)); return Result; exception when Util.Serialize.IO.Parse_Error => raise Invalid_Token with "Invalid JSON content"; end Decode; end Security.OAuth.JWT;