Last active
August 29, 2015 14:04
-
-
Save simonjefford/af965f76a75a7ce0f0ea to your computer and use it in GitHub Desktop.
Salesforce
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Raw Token | |
--------- | |
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjE5MCJ9.eyJleHAiOjE0MDY4MTkwODMsInN1YiI6Imh0dHBzOi8vbG9naW4uc2FsZXNmb3JjZS5jb20vaWQvMDBEMjAwMDAwMDBuVjBhRUFFLzAwNTIwMDAwMDAzaEhsREFBVSIsImF0X2hhc2giOiItZU4tdzgteFZzcm4wVHJKQzh0THp3IiwiYXVkIjoiM01WRzlXdFdTS1VERy54NndzZUhDWklkX055aDVaUU9CZWpKZjRONE55VF9OaVJUd2FsbE5lUjVLMFZ4dzFiWGFJY0JMOWNob2tiQlhpYmtTR01ZUiIsImlzcyI6Imh0dHBzOi8vbG9naW4uc2FsZXNmb3JjZS5jb20iLCJpYXQiOjE0MDY4MTg5NjN9.MnFuklB18wjGotkaWPqcUMb0cRT57UfsPCYUUmJVUur5YNFtimQz6l-7iBzKxow1J6nj-7YRyIbwID5TcXFesnP_aMP62rPNFOIZ-nMfYcoG0FnnIxq5s-thfk0jIJSpv_Teb4p1EdBzKfKKb9rxJ4FGP5AlLloJTfqpU17P82TBIBGKPiT8o19DWYUmdn6kUuzM04rSDc2OaCfb4OqodgzpnBXFbXwpUZi15wqZ97NaGBG6turatUguP3wHRcugD8uXqu0aBzqWoUztAxloQiCIS7mPTmO7EYZcUybZUfKUFPygipN_CrgPzGLtUWTQpBoZ-w8xcjTWzrgUBWW1J6o2FN3Dqr7ecgcfxCCSSTFBmDg3wfp9MOb3ztJoN4MFM-IlSC3m5Bx_loyjj_srRV6VDEW_-WChNIaRiGZG2UuVKeXqMCyckUO89lAikx6U0pQMafgPwTsMoaEVJp2cG7fTt0jzvwuijb65kJq_ACx77fIhH829_17HA9FOVukZWTfPjj9EepEVMd4x16NWCOgU3pSjBdKdmMTbIJ3vXBZE5FA_e1nYv7q2D__7ifHu_OElOvJlxG1yyW8VMity3h8IHQP1sr6xQBpBmOvnw4AIZappctfg-Yu9X6mCsxJQ7S7c5w1ewwu_U7kUXR6x5926WVvDHCc7O15blUyHS44 | |
Header | |
------ | |
{ | |
"alg": "RS256", | |
"typ": "JWT", | |
"kid": "190" | |
} | |
Payload | |
------- | |
{ | |
"sub": "https://login.salesforce.com/id/00D20000000nV0aEAE/00520000003hHlDAAU", | |
"iss": "https://login.salesforce.com", | |
"at_hash": "-eN-w8-xVsrn0TrJC8tLzw", | |
"exp": 1406819083, | |
"iat": 1406818963, | |
"aud": "3MVG9WtWSKUDG.x6wseHCZId_Nyh5ZQOBejJf4N4NyT_NiRTwallNeR5K0Vxw1bXaIcBL9chokbBXibkSGMYR" | |
} | |
Signature | |
--------- | |
MnFuklB18wjGotkaWPqcUMb0cRT57UfsPCYUUmJVUur5YNFtimQz6l-7iBzKxow1J6nj-7YRyIbwID5TcXFesnP_aMP62rPNFOIZ-nMfYcoG0FnnIxq5s-thfk0jIJSpv_Teb4p1EdBzKfKKb9rxJ4FGP5AlLloJTfqpU17P82TBIBGKPiT8o19DWYUmdn6kUuzM04rSDc2OaCfb4OqodgzpnBXFbXwpUZi15wqZ97NaGBG6turatUguP3wHRcugD8uXqu0aBzqWoUztAxloQiCIS7mPTmO7EYZcUybZUfKUFPygipN_CrgPzGLtUWTQpBoZ-w8xcjTWzrgUBWW1J6o2FN3Dqr7ecgcfxCCSSTFBmDg3wfp9MOb3ztJoN4MFM-IlSC3m5Bx_loyjj_srRV6VDEW_-WChNIaRiGZG2UuVKeXqMCyckUO89lAikx6U0pQMafgPwTsMoaEVJp2cG7fTt0jzvwuijb65kJq_ACx77fIhH829_17HA9FOVukZWTfPjj9EepEVMd4x16NWCOgU3pSjBdKdmMTbIJ3vXBZE5FA_e1nYv7q2D__7ifHu_OElOvJlxG1yyW8VMity3h8IHQP1sr6xQBpBmOvnw4AIZappctfg-Yu9X6mCsxJQ7S7c5w1ewwu_U7kUXR6x5926WVvDHCc7O15blUyHS44 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IdentityModel.Tokens; | |
using System.Linq; | |
using System.Net.Http; | |
using System.Threading; | |
using System.Threading.Tasks; | |
using System.Web; | |
using System.Web.Mvc; | |
using Microsoft.IdentityModel.Extensions; | |
using Microsoft.IdentityModel.Protocols; | |
namespace MvcApplication1.Controllers | |
{ | |
public class HomeController : Controller | |
{ | |
// | |
// GET: /Home/ | |
public async Task<ActionResult> Index() | |
{ | |
var manager = new ConfigurationManager<OpenIdConnectConfiguration>("https://emea.salesforce.com/.well-known/openid-configuration", new HttpClient()); | |
var cancelToken = new CancellationTokenSource().Token; | |
var configuration = await manager.GetConfigurationAsync(cancelToken); | |
this.Session["configuration"] = configuration; | |
var uriBuilder = new UriBuilder(configuration.AuthorizationEndpoint); | |
var query = HttpUtility.ParseQueryString(uriBuilder.Query); | |
query.Add("client_id", "<redacted>"); | |
query.Add("response_type", "code"); | |
query.Add("scope", "openid"); | |
query.Add("redirect_uri", "https://localhost:44301/oauthcallback"); | |
uriBuilder.Query = query.ToString(); | |
return this.Redirect(uriBuilder.Uri.ToString()); | |
} | |
public async Task<ActionResult> OauthCallback() | |
{ | |
var code = this.Request["code"]; | |
var client = new HttpClient(); | |
var content = new FormUrlEncodedContent(new Dictionary<string, string>() | |
{ | |
{ "grant_type", "authorization_code"}, | |
{ "client_id", "<redacted>"}, | |
{ "client_secret", "<redacted>"}, | |
{ "redirect_uri", "https://localhost:44301/oauthcallback"}, | |
{ "code", code}, | |
}); | |
var configuration = (OpenIdConnectConfiguration)this.Session["configuration"]; | |
var response = await client.PostAsync(configuration.TokenEndpoint, content); | |
var responseValues = await response.Content.ReadAsAsync<Dictionary<string, string>>(); | |
var converted = responseValues.Select(kvp => new KeyValuePair<string, string[]>(kvp.Key, new string[] { kvp.Value })); | |
var openidMessage = new OpenIdConnectMessage(converted); | |
var handlers = SecurityTokenHandlerCollectionExtensions.GetDefaultHandlers(); | |
SecurityToken token = null; | |
var validationParameters = new TokenValidationParameters | |
{ | |
IssuerSigningTokens = configuration.SigningTokens | |
}; | |
// exception thrown here | |
handlers.ValidateToken(openidMessage.IdToken, validationParameters, out token); | |
return this.View(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<packages> | |
<package id="Microsoft.IdentityModel.Protocol.Extensions" version="1.0.0-RC2" targetFramework="net45" /> | |
<package id="System.IdentityModel.Tokens.Jwt" version="4.0.0-RC2" targetFramework="net45" /> | |
</packages> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IdentityModel.Tokens; | |
using System.IO; | |
using System.Net.Http; | |
using System.Threading; | |
using System.Threading.Tasks; | |
using Microsoft.IdentityModel.Extensions; | |
using Microsoft.IdentityModel.Protocols; | |
namespace ConsoleApplication1 | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
AsyncMain().Wait(); | |
Console.ReadLine(); | |
} | |
private static async Task AsyncMain() | |
{ | |
try | |
{ | |
var tokenString = File.ReadAllText(@"c:\users\sjefford\desktop\jwt.txt"); | |
var manager = new ConfigurationManager<OpenIdConnectConfiguration>("https://login.salesforce.com/.well-known/openid-configuration", new HttpClient()); | |
var cancelToken = new CancellationTokenSource().Token; | |
var configuration = await manager.GetConfigurationAsync(cancelToken); | |
var handlers = SecurityTokenHandlerCollectionExtensions.GetDefaultHandlers(); | |
SecurityToken token = null; | |
var validationParameters = new TokenValidationParameters | |
{ | |
IssuerSigningTokens = configuration.SigningTokens | |
}; | |
handlers.ValidateToken(tokenString, validationParameters, out token); | |
} | |
catch (Exception e) | |
{ | |
Console.WriteLine(e); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"crypto" | |
"crypto/rsa" | |
"crypto/sha256" | |
"encoding/base64" | |
"encoding/json" | |
"errors" | |
"io/ioutil" | |
"log" | |
"math/big" | |
"net/http" | |
"strings" | |
) | |
func getKey() (*rsa.PublicKey, error) { | |
log.Println("getkey: getting key from endpoint") | |
resp, err := http.Get("https://login.salesforce.com/id/keys") | |
if err != nil { | |
log.Fatal(err) | |
return nil, err | |
} | |
log.Println("getkey: key fetched") | |
keyData := make(map[string][]map[string]string) | |
log.Println("getkey: decoding") | |
dec := json.NewDecoder(resp.Body) | |
err = dec.Decode(&keyData) | |
if err != nil { | |
log.Fatal(err) | |
} | |
keys := keyData["keys"] | |
for _, keyMap := range keys { | |
kid := keyMap["kid"] | |
if kid == "190" { | |
modBytes, err := decodeSegment(keyMap["n"]) | |
if err != nil { | |
return nil, err | |
} | |
modInt := new(big.Int) | |
// log.Println(modBytes) | |
modInt.SetBytes(modBytes) | |
rsaKey := new(rsa.PublicKey) | |
rsaKey.N = modInt | |
rsaKey.E = 65537 | |
log.Println("getkey: got the key") | |
return rsaKey, nil | |
} | |
} | |
return nil, errors.New("Key not found") | |
} | |
type jwtData struct { | |
payload []byte | |
signature []byte | |
} | |
func (d *jwtData) hashPayload() []byte { | |
byteArr := sha256.Sum256(d.payload) | |
return byteArr[:sha256.Size] | |
} | |
func decodeSegment(seg string) ([]byte, error) { | |
if l := len(seg) % 4; l > 0 { | |
seg += strings.Repeat("=", 4-l) | |
} | |
return base64.URLEncoding.DecodeString(seg) | |
} | |
func readJwtData(file string) (*jwtData, error) { | |
bytes, err := ioutil.ReadFile(file) | |
if err != nil { | |
return nil, err | |
} | |
var j jwtData | |
str := string(bytes) | |
parts := strings.Split(str, ".") | |
j.payload = []byte(parts[0] + "." + parts[1]) | |
j.signature, err = decodeSegment(parts[2]) | |
// log.Println(j.signature) | |
// log.Println(parts[2]) | |
// log.Println(j.signature)*/ | |
// log.Println(len(j.signature)) | |
return &j, nil | |
} | |
func main() { | |
log.Println("Fetching Key") | |
key, err := getKey() | |
if err != nil { | |
log.Fatal(err) | |
} | |
log.Println("Reading JWT") | |
data, err := readJwtData("jwt.txt") | |
if err != nil { | |
log.Fatal(err) | |
} | |
log.Println("Hashing payload") | |
hash := data.hashPayload() | |
// log.Println(hash) | |
log.Println("Verifying signature") | |
err = rsa.VerifyPKCS1v15(key, crypto.SHA256, hash, data.signature) | |
if err != nil { | |
log.Fatal(err) | |
} | |
log.Println("signature verified") | |
// c := new(big.Int).SetBytes(data.signature) | |
// m := encrypt(new(big.Int), key, c) | |
// k := (key.N.BitLen() + 7) / 8 | |
// em := leftPad(m.Bytes(), k) | |
// log.Println(hash) | |
// log.Println(em) | |
} | |
func leftPad(input []byte, size int) (out []byte) { | |
n := len(input) | |
if n > size { | |
n = size | |
} | |
out = make([]byte, size) | |
copy(out[len(out)-n:], input) | |
return | |
} | |
func encrypt(c *big.Int, pub *rsa.PublicKey, m *big.Int) *big.Int { | |
e := big.NewInt(int64(pub.E)) | |
c.Exp(m, e, pub.N) | |
return c | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
We do find the key but the signature does not match.
What algorithm is used to create the signature?