Skip to content

Instantly share code, notes, and snippets.

@neetsdkasu
Last active May 16, 2017 02:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save neetsdkasu/19f9703f8167213708f751c1c2347599 to your computer and use it in GitHub Desktop.
Save neetsdkasu/19f9703f8167213708f751c1c2347599 to your computer and use it in GitHub Desktop.
【練習】ツイッターで認証やってみた(仮コード)
// test
// author: Leonardone @ NEETSDKASU
open neetsdkasu.Twitter
let consumerToken = {
Key = "key";
Secret = "secret"
}
let oauthToken = {
Key = "key";
Secret = "secret"
}
let pinCode = "0000000"
[<EntryPoint>]
let main _ =
use client = new Client(consumerToken, "oob")
// match OAuth.requestToken client with
match OAuth.accessToken client oauthToken pinCode with
| Some(s) -> printfn "%s" s
| None -> printfn "failed"
0
// Twitter
// author: Leonardone @ NEETSDKASU
namespace neetsdkasu.Twitter
type Token = { Key: string; Secret: string }
type Client(consumerToken: Token, callback: string) =
do
System.Net.ServicePointManager.SecurityProtocol
<- System.Net.ServicePointManager.SecurityProtocol
||| System.Net.SecurityProtocolType.Tls12
let webClient = new System.Net.WebClient()
let encoded_callback = System.Net.WebUtility.UrlEncode(callback)
member this.Callback = encoded_callback
member this.ConsumerToken = consumerToken
member this.WebClient = webClient
interface System.IDisposable with
member this.Dispose() = webClient.Dispose()
// Twitter.OAuth
// author: Leonardone @ NEETSDKASU
namespace neetsdkasu.Twitter
module OAuth =
let param name value = (name, value)
let toOAuthParam =
(+) "OAuth "
<< String.concat ", "
<< List.map (function
(k, v) ->
k + "=\"" + Utility.percentEncode v + "\""
)
let requestTokenApi = "https://api.twitter.com/oauth/request_token"
let requestToken (client: Client) =
let param = [ param "oauth_consumer_key" client.ConsumerToken.Key
; param "oauth_nonce" (Utility.nonce())
; param "oauth_signature_method" "HMAC-SHA1"
; param "oauth_timestamp" (string <| Utility.now() + 10u)
; param "oauth_version" "1.0"
; param "oauth_callback" client.Callback
]
let signature = Utility.signature
"POST" requestTokenApi param
client.ConsumerToken.Secret ""
let oauthParam = toOAuthParam (("oauth_signature", signature) :: param)
do client.WebClient.Headers.Add("Authorization", oauthParam)
try
let res = client.WebClient.UploadData(requestTokenApi, Array.empty)
Some(System.Text.Encoding.ASCII.GetString(res))
with
ex ->
eprintf "%A" ex
None
let accessTokenApi = "https://api.twitter.com/oauth/access_token"
let accessToken (client: Client) oauthToken pincode =
let param = [ param "oauth_consumer_key" client.ConsumerToken.Key
; param "oauth_nonce" (Utility.nonce())
; param "oauth_signature_method" "HMAC-SHA1"
; param "oauth_timestamp" (string <| Utility.now() + 10u)
; param "oauth_version" "1.0"
; param "oauth_token" oauthToken.Key
; param "oauth_verifier" pincode
]
let signature = Utility.signature
"POST" accessTokenApi param
client.ConsumerToken.Secret oauthToken.Secret
let oauthParam = toOAuthParam (("oauth_signature", signature) :: param)
do client.WebClient.Headers.Add("Authorization", oauthParam)
try
let res = client.WebClient.UploadData(accessTokenApi, Array.empty)
Some(System.Text.Encoding.ASCII.GetString(res))
with
ex ->
eprintf "%A" ex
None
// Twitter.Utility
// author: Leonardone @ NEETSDKASU
namespace neetsdkasu.Twitter
module Utility =
let percentEncode s =
System.Uri.EscapeDataString(s)
|> String.collect (fun c ->
match c with
| '!' | '*' | '\'' | '(' | ')' -> System.Uri.HexEscape(c)
| _ -> string c
)
let base64 barr = System.Convert.ToBase64String(barr)
let toBytes (s: string) = System.Text.Encoding.ASCII.GetBytes(s)
let nonce() =
use rng = new System.Security.Cryptography.RNGCryptoServiceProvider()
let arr : byte array = Array.zeroCreate 32
do rng.GetBytes(arr)
base64 arr
|> String.collect (fun c ->
if System.Char.IsLetterOrDigit(c) then
string c
else
""
)
let now =
let baseDate = new System.DateTime(1970, 1, 1)
fun () ->
(System.DateTime.UtcNow - baseDate).TotalSeconds
|> uint32
let genSignatureBaseString mthd api param =
let paramStr =
param
|> List.map (function
(k, v) -> (percentEncode k, percentEncode v)
)
|> List.sortBy fst
|> Seq.map (fun s -> fst s + "=" + snd s)
|> String.concat "&"
|> percentEncode
percentEncode mthd + "&" + percentEncode api + "&" + paramStr
let getSigningKey key1 key2 =
percentEncode key1 + "&" + percentEncode key2
let signature mthd api param key1 key2 =
let signatureBaseString =
toBytes <| genSignatureBaseString mthd api param
let signingKey =
toBytes <| getSigningKey key1 key2
use crypto = new System.Security.Cryptography.HMACSHA1(signingKey)
crypto.ComputeHash(signatureBaseString)
|> base64
// Twitter.Utlity test
// author: Leonardone @ NEETSDKASU
#load "Twitter.Utility.fsx"
open neetsdkasu.Twitter
let tuple name value = (name, value)
// Creating a signature
// https://dev.twitter.com/oauth/overview/creating-signatures
let param = [ tuple "status" "Hello Ladies + Gentlemen, a signed OAuth request!"
; tuple "include_entities" "true"
; tuple "oauth_consumer_key" "xvz1evFS4wEEPTGEFPHBog"
; tuple "oauth_nonce" "kYjzVBB8Y0ZFabxSWbWovY3uYSQ2pTgmZeNu2VS4cg"
; tuple "oauth_signature_method" "HMAC-SHA1"
; tuple "oauth_timestamp" "1318622958"
; tuple "oauth_token" "370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb"
; tuple "oauth_version" "1.0"
]
let consumerSecret = "kAcSOqF21Fu85e7zjz7ZN2U4ZRhfV3WpwPAoE3Z7kBw"
let oauthTokenSecret = "LswwdoUaIvS8ltyTt5jkRh4J50vUPVVHtR2YPi5kE"
let signatureBaseString = "POST&https%3A%2F%2Fapi.twitter.com%2F1%2Fstatuses%2Fupdate.json&include_entities%3Dtrue%26oauth_consumer_key%3Dxvz1evFS4wEEPTGEFPHBog%26oauth_nonce%3DkYjzVBB8Y0ZFabxSWbWovY3uYSQ2pTgmZeNu2VS4cg%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1318622958%26oauth_token%3D370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb%26oauth_version%3D1.0%26status%3DHello%2520Ladies%2520%252B%2520Gentlemen%252C%2520a%2520signed%2520OAuth%2520request%2521"
let signingKey = "kAcSOqF21Fu85e7zjz7ZN2U4ZRhfV3WpwPAoE3Z7kBw&LswwdoUaIvS8ltyTt5jkRh4J50vUPVVHtR2YPi5kE"
let oauthSignature = "tnnArxj06cWHq44gCs1OSKk/jLY="
let api = "https://api.twitter.com/1/statuses/update.json"
do
let sbs = Utility.genSignatureBaseString "POST" api param
if sbs = signatureBaseString then
printfn "signatureBaseString is OK"
else
printfn "%s" sbs
let sk = Utility.getSigningKey consumerSecret oauthTokenSecret
if sk = signingKey then
printfn "signingKey is OK"
else
printfn "%s" sk
let signature = Utility.signature "POST" api param consumerSecret oauthTokenSecret
if signature = oauthSignature then
printfn "signature OK"
else
printfn "%s" signature
;;
@neetsdkasu
Copy link
Author

コードの色付けのためだけにGist上では拡張子をfsxにしてるぽ

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment