0 people like it.

Twitter OAuth

Generates the value string for the "Authorization:" header given Twitter application/user keys and tokens and the parameters for the request being authorized.

  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: 
 53: 
 54: 
 55: 
 56: 
 57: 
 58: 
 59: 
 60: 
 61: 
 62: 
 63: 
 64: 
 65: 
 66: 
 67: 
 68: 
 69: 
 70: 
 71: 
 72: 
 73: 
 74: 
 75: 
 76: 
 77: 
 78: 
 79: 
 80: 
 81: 
 82: 
 83: 
 84: 
 85: 
 86: 
 87: 
 88: 
 89: 
 90: 
 91: 
 92: 
 93: 
 94: 
 95: 
 96: 
 97: 
 98: 
 99: 
100: 
101: 
102: 
103: 
104: 
105: 
106: 
107: 
108: 
109: 
110: 
111: 
112: 
113: 
114: 
115: 
116: 
117: 
118: 
119: 
120: 
121: 
122: 
123: 
124: 
125: 
126: 
127: 
128: 
129: 
130: 
131: 
132: 
133: 
134: 
135: 
136: 
137: 
138: 
139: 
140: 
#if INTERACTIVE
#else
module TwitterAuth
#endif
open System
open System.Text
open System.Net

let percentEncode (sb:StringBuilder) (ch:char) =
    if   '0' <= ch && ch <= '9' then sb.Append(ch)
    elif 'a' <= ch && ch <= 'z' then sb.Append(ch)
    elif 'A' <= ch && ch <= 'Z' then sb.Append(ch)
    else
        match ch with 
        | '-' | '.' | '_'  | '~' -> sb.Append(ch)
        | _ -> 
            sb.Append('%') |> ignore
            sb.AppendFormat("{0:X2}",int(ch))

let (+=) (sb:StringBuilder) (a:string) = sb.Append(a)
let (!*) (s:string) = 
    let sb = StringBuilder()
    for i in 0..s.Length-1 do
        let ch = s.[i]
        percentEncode sb ch |> ignore
    sb.ToString()

let rnd = System.Random()
let nonce() =
    let bytes = Array.create 16 0uy
    rnd.NextBytes(bytes)
    BitConverter.ToString(bytes).Replace("-","")

let epoch = DateTime(1970,1,1)
let timeStamp() =
    let dt = (DateTime.UtcNow - epoch).TotalSeconds |> int
    dt.ToString()

let toUpper (s:string) = s.ToUpper()

let signingKey (consumerSecret:string) tokenSecret = 
    consumerSecret + "&" + tokenSecret
    |> Encoding.ASCII.GetBytes

let parameterString parameters =
    let amp = "&"
    let eq  = "="
    let sb = (new StringBuilder(), parameters) ||> Map.fold (fun sb k v -> sb += k += eq += v += amp)
    sb.Remove(sb.Length-amp.Length,amp.Length).ToString()

let sigBase httpMethod baseUrl parmDataStr = 
    (httpMethod |> toUpper) + "&" + !* baseUrl + "&" + !* parmDataStr

let hmacSha1Sig signKey dataString =
    let data = (dataString:string) |> Encoding.ASCII.GetBytes
    use alg = new System.Security.Cryptography.HMACSHA1(signKey)
    alg.ComputeHash(data) |> Convert.ToBase64String

let buildAuthHdr headerParameters =
    assert (headerParameters |> Map.toSeq |> Seq.length = 7)
    let sb = StringBuilder()
    sb.Append("OAuth ") |> ignore
    let sb = (sb,headerParameters) ||> Map.fold (fun sb k v -> sb += k += "=" += "\"" += v += "\"" += ", ")
    sb.Remove(sb.Length - 2, 2) |> ignore
    let header = sb.ToString()
    header

///Generate the Authorization header string based on the request parameters and keys and tokens
//The process is defined here: https://dev.twitter.com/docs/auth/authorizing-request
let authHeader 
    signKey
    consumerKey
    token
    httpMethod
    baseUrl
    reqParams =
    let secParams =
        [
            "oauth_consumer_key",           !*consumerKey
            "oauth_signature_method" ,      "HMAC-SHA1"
            "oauth_timestamp",              timeStamp()
            "oauth_token",                  !*token
            "oauth_version",                "1.0"
            "oauth_nonce",                  nonce()
        ] |> Map.ofList   
    let parameters = (secParams,reqParams) ||> Map.fold(fun acc k v -> acc|>Map.add !*k !*v)
    let parmStr = parameters |> parameterString
    let data2Sign = sigBase httpMethod baseUrl parmStr
    let sigData = hmacSha1Sig signKey data2Sign
    let headerParameters = secParams |> Map.add "oauth_signature" !*sigData
    buildAuthHdr headerParameters

//test parameters are from here
//https://dev.twitter.com/docs/auth/creating-signature
let testSig() =
    let parameters = 
        [
            "status",                       "Hello Ladies + Gentlemen, a signed OAuth request!"
            "include_entities",             "true"
            "oauth_consumer_key",           "xvz1evFS4wEEPTGEFPHBog"
            "oauth_nonce",                  "88643f5b760c4780814a7101ef796851"
            "oauth_signature_method" ,      "HMAC-SHA1"
            "oauth_timestamp",              "1318622958"
            "oauth_token",                  "370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb"
            "oauth_version",                "1.0"
        ]
        |> List.map (fun (k,v) -> !*k,!*v)
        |> Map.ofList
    let consumerSecret = "kAcSOqF21Fu85e7zjz7ZN2U4ZRhfV3WpwPAoE3Z7kBw"
    let tokenSecret = "LswwdoUaIvS8ltyTt5jkRh4J50vUPVVHtR2YPi5kE"
    let signKey = signingKey consumerSecret tokenSecret
    let httpMethod = "post"
    let baseUrl = "https://api.twitter.com/1/statuses/update.json"
    let parmStr = parameters |> parameterString
    let data = sigBase httpMethod baseUrl parmStr
    let mySig = hmacSha1Sig signKey data
    mySig

let toParmString parms =
    let sb = (StringBuilder(),parms) ||> Map.fold (fun sb k v -> sb += !*k += "=" += !*v += "&")
    sb.Remove(sb.Length-1,1).ToString()

let download (url:string) hdr =
    use wc = new WebClient()
    wc.Headers.Add(HttpRequestHeader.Authorization,hdr)
    wc.DownloadString(url)

//substitute where you see '****' with appropriate values, to test your keys and tokens
let myExample() =
    let consumerKey = "<****my consumer key"
    let consumerSecret = "<****my consumer secret>"
    let token = "<****my access token>"
    let tokenSecret = "<****my token secret>"
    let signKey = signingKey consumerSecret tokenSecret
    let baseUrl = "https://api.twitter.com/1.1/statuses/user_timeline.json"
    let httpMethod = "get"
    let requestQuery = ["user_id", "<****my userid>"] |> Map.ofList
    let authHeader = authHeader signKey consumerKey token httpMethod baseUrl requestQuery
    let url = baseUrl + "?" + (requestQuery |> toParmString)
    download url authHeader
namespace System
namespace System.Text
namespace System.Net
val percentEncode : sb:StringBuilder -> ch:char -> StringBuilder

Full name: Script.percentEncode
val sb : StringBuilder
Multiple items
type StringBuilder =
  new : unit -> StringBuilder + 5 overloads
  member Append : value:string -> StringBuilder + 18 overloads
  member AppendFormat : format:string * arg0:obj -> StringBuilder + 4 overloads
  member AppendLine : unit -> StringBuilder + 1 overload
  member Capacity : int with get, set
  member Chars : int -> char with get, set
  member Clear : unit -> StringBuilder
  member CopyTo : sourceIndex:int * destination:char[] * destinationIndex:int * count:int -> unit
  member EnsureCapacity : capacity:int -> int
  member Equals : sb:StringBuilder -> bool
  ...

Full name: System.Text.StringBuilder

--------------------
StringBuilder() : unit
StringBuilder(capacity: int) : unit
StringBuilder(value: string) : unit
StringBuilder(value: string, capacity: int) : unit
StringBuilder(capacity: int, maxCapacity: int) : unit
StringBuilder(value: string, startIndex: int, length: int, capacity: int) : unit
val ch : char
Multiple items
val char : value:'T -> char (requires member op_Explicit)

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

--------------------
type char = Char

Full name: Microsoft.FSharp.Core.char
StringBuilder.Append(value: char []) : StringBuilder
   (+0 other overloads)
StringBuilder.Append(value: obj) : StringBuilder
   (+0 other overloads)
StringBuilder.Append(value: uint64) : StringBuilder
   (+0 other overloads)
StringBuilder.Append(value: uint32) : StringBuilder
   (+0 other overloads)
StringBuilder.Append(value: uint16) : StringBuilder
   (+0 other overloads)
StringBuilder.Append(value: decimal) : StringBuilder
   (+0 other overloads)
StringBuilder.Append(value: float) : StringBuilder
   (+0 other overloads)
StringBuilder.Append(value: float32) : StringBuilder
   (+0 other overloads)
StringBuilder.Append(value: int64) : StringBuilder
   (+0 other overloads)
StringBuilder.Append(value: int) : StringBuilder
   (+0 other overloads)
val ignore : value:'T -> unit

Full name: Microsoft.FSharp.Core.Operators.ignore
StringBuilder.AppendFormat(format: string, [<ParamArray>] args: obj []) : StringBuilder
StringBuilder.AppendFormat(format: string, arg0: obj) : StringBuilder
StringBuilder.AppendFormat(provider: IFormatProvider, format: string, [<ParamArray>] args: obj []) : StringBuilder
StringBuilder.AppendFormat(format: string, arg0: obj, arg1: obj) : StringBuilder
StringBuilder.AppendFormat(format: string, arg0: obj, arg1: obj, arg2: obj) : StringBuilder
Multiple items
val int : value:'T -> int (requires member op_Explicit)

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

--------------------
type int = int32

Full name: Microsoft.FSharp.Core.int

--------------------
type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>
val a : string
Multiple items
val string : value:'T -> string

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

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

Full name: Microsoft.FSharp.Core.string
val s : string
val i : int32
property String.Length: int
StringBuilder.ToString() : string
StringBuilder.ToString(startIndex: int, length: int) : string
val rnd : Random

Full name: Script.rnd
Multiple items
type Random =
  new : unit -> Random + 1 overload
  member Next : unit -> int + 2 overloads
  member NextBytes : buffer:byte[] -> unit
  member NextDouble : unit -> float

Full name: System.Random

--------------------
Random() : unit
Random(Seed: int) : unit
val nonce : unit -> string

Full name: Script.nonce
val bytes : byte []
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 create : count:int -> value:'T -> 'T []

Full name: Microsoft.FSharp.Collections.Array.create
Random.NextBytes(buffer: byte []) : unit
type BitConverter =
  static val IsLittleEndian : bool
  static member DoubleToInt64Bits : value:float -> int64
  static member GetBytes : value:bool -> byte[] + 9 overloads
  static member Int64BitsToDouble : value:int64 -> float
  static member ToBoolean : value:byte[] * startIndex:int -> bool
  static member ToChar : value:byte[] * startIndex:int -> char
  static member ToDouble : value:byte[] * startIndex:int -> float
  static member ToInt16 : value:byte[] * startIndex:int -> int16
  static member ToInt32 : value:byte[] * startIndex:int -> int
  static member ToInt64 : value:byte[] * startIndex:int -> int64
  ...

Full name: System.BitConverter
BitConverter.ToString(value: byte []) : string
BitConverter.ToString(value: byte [], startIndex: int) : string
BitConverter.ToString(value: byte [], startIndex: int, length: int) : string
val epoch : DateTime

Full name: Script.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)
val timeStamp : unit -> string

Full name: Script.timeStamp
val dt : int
property DateTime.UtcNow: DateTime
Int32.ToString() : string
Int32.ToString(provider: IFormatProvider) : string
Int32.ToString(format: string) : string
Int32.ToString(format: string, provider: IFormatProvider) : string
val toUpper : s:string -> string

Full name: Script.toUpper
String.ToUpper() : string
String.ToUpper(culture: Globalization.CultureInfo) : string
val signingKey : consumerSecret:string -> tokenSecret:string -> byte []

Full name: Script.signingKey
val consumerSecret : string
val tokenSecret : string
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.ASCII: 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 parameterString : parameters:Map<string,string> -> string

Full name: Script.parameterString
val parameters : Map<string,string>
val amp : string
val eq : 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 fold : folder:('State -> 'Key -> 'T -> 'State) -> state:'State -> table:Map<'Key,'T> -> 'State (requires comparison)

Full name: Microsoft.FSharp.Collections.Map.fold
val k : string
val v : string
StringBuilder.Remove(startIndex: int, length: int) : StringBuilder
property StringBuilder.Length: int
val sigBase : httpMethod:string -> baseUrl:string -> parmDataStr:string -> string

Full name: Script.sigBase
val httpMethod : string
val baseUrl : string
val parmDataStr : string
val hmacSha1Sig : signKey:byte [] -> dataString:string -> string

Full name: Script.hmacSha1Sig
val signKey : byte []
val dataString : string
val data : byte []
val alg : Security.Cryptography.HMACSHA1
namespace System.Security
namespace System.Security.Cryptography
Multiple items
type HMACSHA1 =
  inherit HMAC
  new : unit -> HMACSHA1 + 2 overloads

Full name: System.Security.Cryptography.HMACSHA1

--------------------
Security.Cryptography.HMACSHA1() : unit
Security.Cryptography.HMACSHA1(key: byte []) : unit
Security.Cryptography.HMACSHA1(key: byte [], useManagedSha1: bool) : unit
Security.Cryptography.HashAlgorithm.ComputeHash(buffer: byte []) : byte []
Security.Cryptography.HashAlgorithm.ComputeHash(inputStream: IO.Stream) : byte []
Security.Cryptography.HashAlgorithm.ComputeHash(buffer: byte [], offset: int, count: int) : byte []
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.ToBase64String(inArray: byte []) : string
Convert.ToBase64String(inArray: byte [], options: Base64FormattingOptions) : string
Convert.ToBase64String(inArray: byte [], offset: int, length: int) : string
Convert.ToBase64String(inArray: byte [], offset: int, length: int, options: Base64FormattingOptions) : string
val buildAuthHdr : headerParameters:Map<string,string> -> string

Full name: Script.buildAuthHdr
val headerParameters : Map<string,string>
val toSeq : table:Map<'Key,'T> -> seq<'Key * 'T> (requires comparison)

Full name: Microsoft.FSharp.Collections.Map.toSeq
module Seq

from Microsoft.FSharp.Collections
val length : source:seq<'T> -> int

Full name: Microsoft.FSharp.Collections.Seq.length
val header : string
val authHeader : signKey:byte [] -> consumerKey:string -> token:string -> httpMethod:string -> baseUrl:string -> reqParams:Map<string,string> -> string

Full name: Script.authHeader


Generate the Authorization header string based on the request parameters and keys and tokens
val consumerKey : string
val token : string
val reqParams : Map<string,string>
val secParams : Map<string,string>
val ofList : elements:('Key * 'T) list -> Map<'Key,'T> (requires comparison)

Full name: Microsoft.FSharp.Collections.Map.ofList
val acc : Map<string,string>
val add : key:'Key -> value:'T -> table:Map<'Key,'T> -> Map<'Key,'T> (requires comparison)

Full name: Microsoft.FSharp.Collections.Map.add
val parmStr : string
val data2Sign : string
val sigData : string
val testSig : unit -> string

Full name: Script.testSig
Multiple items
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
  | ( [] )
  | ( :: ) of Head: 'T * Tail: 'T list
  interface IEnumerable
  interface IEnumerable<'T>
  member Head : 'T
  member IsEmpty : bool
  member Item : index:int -> 'T with get
  member Length : int
  member Tail : 'T list
  static member Cons : head:'T * tail:'T list -> 'T list
  static member Empty : 'T list

Full name: Microsoft.FSharp.Collections.List<_>
val map : mapping:('T -> 'U) -> list:'T list -> 'U list

Full name: Microsoft.FSharp.Collections.List.map
val data : string
val mySig : string
val toParmString : parms:Map<string,string> -> string

Full name: Script.toParmString
val parms : Map<string,string>
val download : url:string -> hdr:string -> string

Full name: Script.download
val url : string
val hdr : string
val wc : WebClient
Multiple items
type WebClient =
  inherit Component
  new : unit -> WebClient
  member BaseAddress : string with get, set
  member CachePolicy : RequestCachePolicy with get, set
  member CancelAsync : unit -> unit
  member Credentials : ICredentials with get, set
  member DownloadData : address:string -> byte[] + 1 overload
  member DownloadDataAsync : address:Uri -> unit + 1 overload
  member DownloadFile : address:string * fileName:string -> unit + 1 overload
  member DownloadFileAsync : address:Uri * fileName:string -> unit + 1 overload
  member DownloadString : address:string -> string + 1 overload
  ...

Full name: System.Net.WebClient

--------------------
WebClient() : unit
property WebClient.Headers: WebHeaderCollection
Collections.Specialized.NameValueCollection.Add(c: Collections.Specialized.NameValueCollection) : unit
WebHeaderCollection.Add(header: string) : unit
WebHeaderCollection.Add(name: string, value: string) : unit
WebHeaderCollection.Add(header: HttpResponseHeader, value: string) : unit
WebHeaderCollection.Add(header: HttpRequestHeader, value: string) : unit
type HttpRequestHeader =
  | CacheControl = 0
  | Connection = 1
  | Date = 2
  | KeepAlive = 3
  | Pragma = 4
  | Trailer = 5
  | TransferEncoding = 6
  | Upgrade = 7
  | Via = 8
  | Warning = 9
  ...

Full name: System.Net.HttpRequestHeader
field HttpRequestHeader.Authorization = 24
WebClient.DownloadString(address: Uri) : string
WebClient.DownloadString(address: string) : string
val myExample : unit -> string

Full name: Script.myExample
val requestQuery : Map<string,string>
val authHeader : string
Raw view New version

More information

Link:http://fssnip.net/dV
Posted:4 years ago
Author:Faisal Waris
Tags: twitter; authorization