0 people like it.

Verify Azure-ACS issued OAuth Simple Web Token

Verifies the OAuth SWT (simple web token) issued by Azure ACS The SWT may be obtained by many methods; one way is: - "How to: Request a Token from ACS via the OAuth WRAP Protocol" (http://msdn.microsoft.com/en-us/library/windowsazure/hh674475.aspx) (Note I used the userid/password method to obtain the token on behalf of a 'service identity' set up in ACS) The token is normally verifed by a 'relying party' such as an ASP.Net website hosting a Web API General ACS documentation is here: http://msdn.microsoft.com/en-us/library/gg429788.aspx

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
module OAuthVerify
//verifies the OAuth SWT (simple web token) issued by Azure ACS
//The SWT may be obtained by many methods; one way is:
// - "How to: Request a Token from ACS via the OAuth WRAP Protocol"
//   (http://msdn.microsoft.com/en-us/library/windowsazure/hh674475.aspx)
//(Note I used the userid/password method to obtain the token on behalf of a 'service identity' set up in ACS)
//The token is normally verifed by a 'relying party' such as an ASP.Net website hosting a Web API
//General ACS documentation is here: http://msdn.microsoft.com/en-us/library/gg429788.aspx
open System
open System.Web
open System.Text
open System.Security.Cryptography

//the shared symmetric key for the Relying Party that is setup in Azure ACS. 
//ACS signs the token with this key
let private key = "....RqUfo=" 

let split cs (s:string) = s.Split(cs |> Seq.toArray)
let join sep (xs:string array) = String.Join(sep,xs)
let epoch = DateTime (1970,1,1,0,0,0,  DateTimeKind .Utc)

let validate oauthSWT = 
    let signedParts =
        oauthSWT
        |> HttpUtility.UrlDecode
        |> split ['&']
        |> Array.rev
        |> Seq.skip 1
        |> Seq.toArray 
        |> Array.rev
        |> join "&"

    let hmac256Sig =
        oauthSWT
        |> HttpUtility.UrlDecode
        |> split ['&']
        |> Array.rev
        |> Seq.nth 0
        |> split ['=']
        |> Seq.nth 1
        |> HttpUtility.UrlDecode
        |> Convert.FromBase64String

    use hmacVerify = new HMACSHA256(Convert.FromBase64String key)
    let computedSig = hmacVerify.ComputeHash(Encoding.UTF8.GetBytes signedParts)
    if  hmac256Sig <> computedSig then failwith "computed signnature does not match token signature"

    let assertions = signedParts |> split ['&'] |> Array.map (split ['=']) |> Array.map (fun xs -> xs.[0], xs.[1]) |> Map.ofArray
    //check assertions - only expiry is checked here
    let expires = assertions.["ExpiresOn"] |> float 
    let expireTime = epoch.AddSeconds expires
    if DateTime.UtcNow > expireTime then failwith "token is expired"
module OAuthVerify
namespace System
namespace System.Web
namespace System.Text
namespace System.Security
namespace System.Security.Cryptography
val private key : string

Full name: OAuthVerify.key
val split : cs:seq<char> -> s:string -> string []

Full name: OAuthVerify.split
val cs : seq<char>
val s : string
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = String

Full name: Microsoft.FSharp.Core.string
String.Split([<ParamArray>] separator: char []) : string []
String.Split(separator: string [], options: StringSplitOptions) : string []
String.Split(separator: char [], options: StringSplitOptions) : string []
String.Split(separator: char [], count: int) : string []
String.Split(separator: string [], count: int, options: StringSplitOptions) : string []
String.Split(separator: char [], count: int, options: StringSplitOptions) : string []
module Seq

from Microsoft.FSharp.Collections
val toArray : source:seq<'T> -> 'T []

Full name: Microsoft.FSharp.Collections.Seq.toArray
val join : sep:string -> xs:string array -> string

Full name: OAuthVerify.join
val sep : string
val xs : string array
type 'T array = 'T []

Full name: Microsoft.FSharp.Core.array<_>
Multiple items
type String =
  new : value:char -> string + 7 overloads
  member Chars : int -> char
  member Clone : unit -> obj
  member CompareTo : value:obj -> int + 1 overload
  member Contains : value:string -> bool
  member CopyTo : sourceIndex:int * destination:char[] * destinationIndex:int * count:int -> unit
  member EndsWith : value:string -> bool + 2 overloads
  member Equals : obj:obj -> bool + 2 overloads
  member GetEnumerator : unit -> CharEnumerator
  member GetHashCode : unit -> int
  ...

Full name: System.String

--------------------
String(value: nativeptr<char>) : unit
String(value: nativeptr<sbyte>) : unit
String(value: char []) : unit
String(c: char, count: int) : unit
String(value: nativeptr<char>, startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int) : unit
String(value: char [], startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int, enc: Encoding) : unit
String.Join(separator: string, values: Collections.Generic.IEnumerable<string>) : string
String.Join<'T>(separator: string, values: Collections.Generic.IEnumerable<'T>) : string
String.Join(separator: string, [<ParamArray>] values: obj []) : string
String.Join(separator: string, [<ParamArray>] value: string []) : string
String.Join(separator: string, value: string [], startIndex: int, count: int) : string
val epoch : DateTime

Full name: OAuthVerify.epoch
Multiple items
type DateTime =
  struct
    new : ticks:int64 -> DateTime + 10 overloads
    member Add : value:TimeSpan -> DateTime
    member AddDays : value:float -> DateTime
    member AddHours : value:float -> DateTime
    member AddMilliseconds : value:float -> DateTime
    member AddMinutes : value:float -> DateTime
    member AddMonths : months:int -> DateTime
    member AddSeconds : value:float -> DateTime
    member AddTicks : value:int64 -> DateTime
    member AddYears : value:int -> DateTime
    ...
  end

Full name: System.DateTime

--------------------
DateTime()
   (+0 other overloads)
DateTime(ticks: int64) : unit
   (+0 other overloads)
DateTime(ticks: int64, kind: DateTimeKind) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, calendar: Globalization.Calendar) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, kind: DateTimeKind) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, calendar: Globalization.Calendar) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int) : unit
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int, kind: DateTimeKind) : unit
   (+0 other overloads)
type DateTimeKind =
  | Unspecified = 0
  | Utc = 1
  | Local = 2

Full name: System.DateTimeKind
val validate : oauthSWT:string -> unit

Full name: OAuthVerify.validate
val oauthSWT : string
val signedParts : string
Multiple items
type HttpUtility =
  new : unit -> HttpUtility
  static member HtmlAttributeEncode : s:string -> string + 1 overload
  static member HtmlDecode : s:string -> string + 1 overload
  static member HtmlEncode : s:string -> string + 2 overloads
  static member JavaScriptStringEncode : value:string -> string + 1 overload
  static member ParseQueryString : query:string -> NameValueCollection + 1 overload
  static member UrlDecode : str:string -> string + 3 overloads
  static member UrlDecodeToBytes : str:string -> byte[] + 3 overloads
  static member UrlEncode : str:string -> string + 3 overloads
  static member UrlEncodeToBytes : str:string -> byte[] + 3 overloads
  ...

Full name: System.Web.HttpUtility

--------------------
HttpUtility() : unit
HttpUtility.UrlDecode(str: string) : string
HttpUtility.UrlDecode(bytes: byte [], e: Encoding) : string
HttpUtility.UrlDecode(str: string, e: Encoding) : string
HttpUtility.UrlDecode(bytes: byte [], offset: int, count: int, e: Encoding) : string
type Array =
  member Clone : unit -> obj
  member CopyTo : array:Array * index:int -> unit + 1 overload
  member GetEnumerator : unit -> IEnumerator
  member GetLength : dimension:int -> int
  member GetLongLength : dimension:int -> int64
  member GetLowerBound : dimension:int -> int
  member GetUpperBound : dimension:int -> int
  member GetValue : [<ParamArray>] indices:int[] -> obj + 7 overloads
  member Initialize : unit -> unit
  member IsFixedSize : bool
  ...

Full name: System.Array
val rev : array:'T [] -> 'T []

Full name: Microsoft.FSharp.Collections.Array.rev
val skip : count:int -> source:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.skip
val hmac256Sig : byte []
val nth : index:int -> source:seq<'T> -> 'T

Full name: Microsoft.FSharp.Collections.Seq.nth
type Convert =
  static val DBNull : obj
  static member ChangeType : value:obj * typeCode:TypeCode -> obj + 3 overloads
  static member FromBase64CharArray : inArray:char[] * offset:int * length:int -> byte[]
  static member FromBase64String : s:string -> byte[]
  static member GetTypeCode : value:obj -> TypeCode
  static member IsDBNull : value:obj -> bool
  static member ToBase64CharArray : inArray:byte[] * offsetIn:int * length:int * outArray:char[] * offsetOut:int -> int + 1 overload
  static member ToBase64String : inArray:byte[] -> string + 3 overloads
  static member ToBoolean : value:obj -> bool + 17 overloads
  static member ToByte : value:obj -> byte + 18 overloads
  ...

Full name: System.Convert
Convert.FromBase64String(s: string) : byte []
val hmacVerify : HMACSHA256
Multiple items
type HMACSHA256 =
  inherit HMAC
  new : unit -> HMACSHA256 + 1 overload

Full name: System.Security.Cryptography.HMACSHA256

--------------------
HMACSHA256() : unit
HMACSHA256(key: byte []) : unit
val computedSig : byte []
HashAlgorithm.ComputeHash(buffer: byte []) : byte []
HashAlgorithm.ComputeHash(inputStream: IO.Stream) : byte []
HashAlgorithm.ComputeHash(buffer: byte [], offset: int, count: int) : byte []
type Encoding =
  member BodyName : string
  member Clone : unit -> obj
  member CodePage : int
  member DecoderFallback : DecoderFallback with get, set
  member EncoderFallback : EncoderFallback with get, set
  member EncodingName : string
  member Equals : value:obj -> bool
  member GetByteCount : chars:char[] -> int + 3 overloads
  member GetBytes : chars:char[] -> byte[] + 5 overloads
  member GetCharCount : bytes:byte[] -> int + 2 overloads
  ...

Full name: System.Text.Encoding
property Encoding.UTF8: Encoding
Encoding.GetBytes(s: string) : byte []
Encoding.GetBytes(chars: char []) : byte []
Encoding.GetBytes(chars: char [], index: int, count: int) : byte []
Encoding.GetBytes(chars: nativeptr<char>, charCount: int, bytes: nativeptr<byte>, byteCount: int) : int
Encoding.GetBytes(s: string, charIndex: int, charCount: int, bytes: byte [], byteIndex: int) : int
Encoding.GetBytes(chars: char [], charIndex: int, charCount: int, bytes: byte [], byteIndex: int) : int
val failwith : message:string -> 'T

Full name: Microsoft.FSharp.Core.Operators.failwith
val assertions : Map<string,string>
val map : mapping:('T -> 'U) -> array:'T [] -> 'U []

Full name: Microsoft.FSharp.Collections.Array.map
val xs : string []
Multiple items
module Map

from Microsoft.FSharp.Collections

--------------------
type Map<'Key,'Value (requires comparison)> =
  interface IEnumerable
  interface IComparable
  interface IEnumerable<KeyValuePair<'Key,'Value>>
  interface ICollection<KeyValuePair<'Key,'Value>>
  interface IDictionary<'Key,'Value>
  new : elements:seq<'Key * 'Value> -> Map<'Key,'Value>
  member Add : key:'Key * value:'Value -> Map<'Key,'Value>
  member ContainsKey : key:'Key -> bool
  override Equals : obj -> bool
  member Remove : key:'Key -> Map<'Key,'Value>
  ...

Full name: Microsoft.FSharp.Collections.Map<_,_>

--------------------
new : elements:seq<'Key * 'Value> -> Map<'Key,'Value>
val ofArray : elements:('Key * 'T) [] -> Map<'Key,'T> (requires comparison)

Full name: Microsoft.FSharp.Collections.Map.ofArray
val expires : float
Multiple items
val float : value:'T -> float (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.float

--------------------
type float = Double

Full name: Microsoft.FSharp.Core.float

--------------------
type float<'Measure> = float

Full name: Microsoft.FSharp.Core.float<_>
val expireTime : DateTime
DateTime.AddSeconds(value: float) : DateTime
property DateTime.UtcNow: DateTime

More information

Link:http://fssnip.net/lj
Posted:10 years ago
Author:Faisal Waris
Tags: oauth , azure , acs , authentication , authorization