Authentication คือ การพิสูจน์ตัวตนเพื่อความปลอดภัยในส่งข้อมูลระหว่าง Client กับ Server โดยเราสามารถดูตัวอย่างได้จาก postman ได้ง่ายและเร็วในการศึกษา หรือจะพูดได้ว่าเป็นหลักการ Reverse engineering ก็ได้มั่ง เพื่อที่จะทำเป็นมาตรฐานได้ดังนี้

authorization-tab-v9

No auth

ง่ายๆ สั้นๆ คือ ไม่การส่งข้อมูลที่ต้องพิสูจน์ตัวตนอะไรเลย สามารถใช้งานได้แบบสาธารณะ

API key

คือการส่งข้อมูลขออนุญาตเข้าใช้งาน Key และ Value ผ่าน Header หรือ Quuery Params เพื่อตรวจสิทธิ์ในการเข้าใช้งาน

api-key

Bearer token

เป็นการส่ง Token เพื่อตรวจสิทธิ์ในการเข้าใช้งาน โดยจะมี Prefix ของข้อมูลหน้า Token ที่ส่งไปใน Header ว่า Bearer

Bearer-type

Basic auth

คือการส่งข้อมูล Username และ Password โดยข้อมูลจะถูก Encode เป็น base64 แล้วถูกส่งไปใน Header

basic-type
const USERNAME = 'username';
const PASSWORD = 'password';

const authBasic = `Basic ${Buffer.from(USERNAME + ':' + PASSWORD).toString('base64')}`
console.log(authBasic);
//Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Digest auth

คือการตรวจสอบสิทธิ์การเข้าใช้งาน ด้วยวิธีการเข้ารหัสข้อมูลโดยใช้ Algorithm MD5 และ SHA ในการตรวจสอบความถูกต้องของข้อมูล โดยมีขั้นตอนที่ยุ่งยากดังนี้

digest_access_authentication

ตัวอย่าง Algorithm MD5 โดยจะมีขั้นตอนดังนี้

จำเป็นต้องมีข้อมูลที่ใช้ดังนี้

  • username คือ สิ่งที่ใช้ในการระบุตัวตนผู้ใช้งาน
  • password คือ สิ่งที่ใช้ในการพิสูจน์ตัวตนผู้ใช้งาน
  • realm คือ string อะไรก็ได้ที่ระบุจาก Server
  • method คือ รูปแบบของการส่งข้อมูลไปยัง Server เช่น GET, POST etc.
  • uri คือ ข้อมูลที่ใช้ระบุตัวตนของทรัพยากร (resource) หรือ path ที่ใช้เข้าถึง resource
  • nonce คือ unique string อะไรก็ได้ที่ระบุจาก Server

ข้อมูล Authentication ที่จะส่งไปกับ Header จะมีรูปแบบดังนี้

Digest username="username",
       realm="test@mail.com",
       nonce="",
       uri="/test",
       algorithm="MD5",
       response="c62f1813b146be5382eba6861873c831"

สิ่งที่ต้องการคำนวณหาคือ response โดยมีวิธีคำนวณดังนี้

const crypto = require('crypto')

const username = 'username';
const password = 'password';
const realm = 'test@mail.com';
const method = 'GET';
const uri = '/test';
const nonce = '';
// function hashing MD5
const MD5 = (text) => {
    let hash = crypto.createHash('md5');
    //passing the data to be hashed
    let data = hash.update(text, 'utf-8');
    //Creating the hash in the required format
    let gen_hash = data.digest('hex');
    return gen_hash;
}
const HA1 = MD5(`${username}:${realm}:${password}`);
console.log(HA1);
// 63d45584ce377359e346690bde490668

const HA2 = MD5(`${method}:${uri}`);
console.log(HA2);
// e2b43a77e8b6707afcc1571382ca7c73

const response = MD5(`${HA1}:${nonce}:${HA2}`);
console.log(response);
// c62f1813b146be5382eba6861873c831

สามารถเปลี่ยน Algorithm เป็น MD5, SHA-256 และ SHA-512-256 แต่ขั้นตอนก็ยังเหมือนเดิม

📄digest-auth-md5.js

ตัวอย่าง Algorithm MD5-sess โดยจะมีขั้นตอนดังนี้

จำเป็นต้องมีข้อมูลที่ใช้ดังนี้

  • username คือ สิ่งที่ใช้ในการระบุตัวตนผู้ใช้งาน
  • password คือ สิ่งที่ใช้ในการพิสูจน์ตัวตนผู้ใช้งาน
  • realm คือ string อะไรก็ได้ที่ระบุจาก Server
  • method คือ รูปแบบของการส่งข้อมูลไปยัง Server เช่น GET, POST etc.
  • uri คือ ข้อมูลที่ใช้ระบุตัวตนของทรัพยากร (resource) หรือ path ที่ใช้เข้าถึง resource
  • nonce คือ unique string อะไรก็ได้ที่ระบุจาก Server
  • cnonce คือ สิ่งที่ป้องกันการโจมตี ใหการเข้ารหัส
  • nc คือ เลขฐานสิบหก ที่นับจำนวน Request ของ API
  • qop คือ string ที่ระบุจาก Server

ข้อมูล Authentication ที่จะส่งไปกับ Header จะมีรูปแบบดังนี้

Digest username="username",
       realm="test@mail.com",
       nonce="",
       uri="/test",
       algorithm="MD5-sess",
       qop=auth,
       nc=12,
       cnonce="0a4f113b",
       response="49902a9875ea6b847ba59bc0162bc294",
       opaque="7f40e41"

สิ่งที่ต้องการคำนวณหาคือ response โดยมีวิธีคำนวณดังนี้

const crypto = require('crypto')

const username = 'username';
const password = 'password';
const realm = 'test@mail.com';
const method = 'GET';
const uri = '/test';
const nonce = '';
const cnonce = '0a4f113b';
const nc = 12;
const qop = 'auth';
// function hasing MD5
const MD5 = (text) => {
    let hash = crypto.createHash('md5');
    //passing the data to be hashed
    let data = hash.update(text, 'utf-8');
    //Creating the hash in the required format
    let gen_hash = data.digest('hex');
    return gen_hash;
}
const HA1 = MD5(`${MD5(`${username}:${realm}:${password}`)}:${nonce}:${cnonce}`);
console.log(HA1);
// af6737a901699ef33e2186c3e8ff78b3

const HA2 = MD5(`${method}:${uri}`);
console.log(HA2);
// e2b43a77e8b6707afcc1571382ca7c73

const response = MD5(`${HA1}:${nonce}:${nc}:${cnonce}:${qop}:${HA2}`);
console.log(response);
// 49902a9875ea6b847ba59bc0162bc294

สามารถเปลี่ยน Algorithm เป็น MD5-sess, SHA-256-sess และ SHA-512-256-sess แต่ขั้นตอนก็ยังเหมือนเดิม

📄digest-auth-md5-sess.js

OAuth 1.0

ตัวอย่าง Signature ด้วย Algorithm HMAC-SHA1

ข้อมูล Authentication ที่จะส่งไปกับ Header จะมีรูปแบบดังนี้

OAuth oauth_consumer_key="RKCGzna7bv9YD57c",
      oauth_signature_method="HMAC-SHA1",
      oauth_timestamp="1472121255",
      oauth_nonce="e5VR16",
      oauth_version="1.0",
      oauth_signature="Or%2F2PqPg21wp967CASJtoo%2BF5Kk%3D"

วิธีการคำนวณหา oauth_signature ได้ดังนี้

จำเป็นต้องมีข้อมูลที่ใช้ดังนี้

  • Consumer Key
  • Consumer Secret
  • base_url
  • method
  • timestamp
  • nonce
  • parameters
const crypto = require('crypto')

const customerKey = "RKCGzna7bv9YD57c";
const customerSecret = encodeURIComponent("D+EdQ-gs$-%@2Nu7");
const base_url = "https://postman-echo.com/oauth1";
const method = "GET";
const timestamp = "1472121255";
const nonce = "e5VR16";
const parameters = {
    oauth_consumer_key: customerKey,
    oauth_signature_method: "HMAC-SHA1",
    oauth_timestamp: timestamp,
    oauth_nonce: encodeURIComponent(nonce),
    oauth_version: "1.0"
}
// sort object by key
const oauth_parameter_string_object_ordered = {};
Object.keys(parameters).sort().forEach(function (key) {
    oauth_parameter_string_object_ordered[key] = parameters[key];
});

// convert object into array
const oauth_parameter_string_array = [];
for (var key in oauth_parameter_string_object_ordered) {
    oauth_parameter_string_array.push(`${key}=${oauth_parameter_string_object_ordered[key]}`);
}

// generate parameter string
const oauth_parameter_string = oauth_parameter_string_array.join('&');
const encodedUrl = encodeURIComponent(base_url);
const signature_base_string = `${method}&${encodedUrl}&${encodeURIComponent(oauth_parameter_string)}`
console.log(signature_base_string)
const signing_key = `${customerSecret}&`;

const oauth_signature = crypto.createHmac("sha1", signing_key).update(signature_base_string).digest('base64');
console.log(oauth_signature);

const encoded_oauth_signature = encodeURIComponent(oauth_signature);
console.log(encoded_oauth_signature);

สามารถเปลี่ยน Algorithm เป็น HMAC-SHA1, HMAC-SHA256, และ HMAC-SHA512 แค่วิธีการคำนวณก็ยังสามารถทำแบบเดิมได้

📄OAuth-1.0-HMAC-SHA1.js

ตัวอย่าง Signature ด้วย Algorithm RSA-SHA1

ข้อมูล Authentication ที่จะส่งไปกับ Header จะมีรูปแบบดังนี้

OAuth oauth_consumer_key="RKCGzna7bv9YD57c",
      oauth_signature_method="RSA-SHA1",
      oauth_timestamp="1472121255",
      oauth_nonce="e5VR16",
      oauth_version="1.0",
      oauth_signature="F9CBjycTpUgOOWk7hSLClpESVs9RB1gXrCrNdol%2FQsAmrL2HklZTJtRf51aahvpSeYtUJAYDunYiaYEGURB6k0HF82xkZ5kx2AgF%2B9xRuhMdYR55wNsik59Rm2mSpC%2FtceKZ7B3AHNHUto%2FTUn5jghZfdfENhjZEX0WQbQbSURg%3D"

วิธีการคำนวณหา oauth_signature ได้ดังนี้

จำเป็นต้องมีข้อมูลที่ใช้ดังนี้

  • Consumer Key
  • Private Key
  • base_url
  • method
  • timestamp
  • nonce
  • parameters
const crypto = require('crypto')

const customerKey = "RKCGzna7bv9YD57c";
const base_url = "https://postman-echo.com/oauth1";
const method = "GET";
const timestamp = "1472121255";
const nonce = "e5VR16";

const privateKey = `-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQC7vSldvzOQ8/wpaDOVaYaTYamFtNCz2pp9GIxsmVcPVALIo3iM
04+eQUyyx2mTZ4xtxLYiR0XV3+hIG7ftxtsz+FrGJKOsL4fUdPLFeoqCgjzVJ8wA
kVdKx8VStIlNdrhUko8f/ezh8JPP6Lpg5ISpbW/I7LAvtCGnmxVOOa2eRwIDAQAB
AoGAPkBMDiTPUXpFm+lMaXezQv14O7ioF2seHOrd7UivQIrn3WWvHGsuTRhz+Tf8
Pv9v5hn7FsSxWGjFWduvEm4E0tZCryKd3KcW4EyhY6e6eA/eW2Xka8ayFav6SkQB
BsT6NVbV6+hMpAew75s9288Snm0TPiWPWSTg9fertqv3RwECQQDjoE6POpVDDPp3
AZ2z1tVYObiRaAeqyMcF1xUboQbvnvgw0XVS8ZnE8jTBmbXWC0FxVyEyIBz6Kai9
e7yORsnHAkEA0yQG1G+KwtR140xkKUFZnQ3+XicqbI958Zg3nACLuc1cmuh6zS93
GYNu1TaFLu+d3zbzp+KQI1HVsovXP5aHgQJBANWLsAfI8vz7cQIyfuuXsYDabd/k
E8VSJPzCoifQcrxcjATojEPrKtJMU9gIx0FuP8//6MGoxOagLJDPQ77KhEMCQQCt
tgNEfiyc1K3U/wGdC54N3/h6QCDgRj7erQx7ddt/V10sOb7m13lWbVMfagazMgMi
JZTbeER8OpTlm7XRJCiBAkBK8pDtU63QQId2Bi89ShtXjw2L9imrdl8LAP6IlWNO
K8QYvI3WnOXZPHLzCLMV7SRbinTAxUlOhcg7vxVy5RKt
-----END RSA PRIVATE KEY-----`
const parameters = {
    oauth_consumer_key: customerKey,
    oauth_signature_method: "RSA-SHA1",
    oauth_timestamp: timestamp,
    oauth_nonce: encodeURIComponent(nonce),
    oauth_version: "1.0"
}
// sort object by key
const oauth_parameter_string_object_ordered = {};
Object.keys(parameters).sort().forEach(function (key) {
    oauth_parameter_string_object_ordered[key] = parameters[key];
});

// convert object into array
const oauth_parameter_string_array = [];
for (var key in oauth_parameter_string_object_ordered) {
    oauth_parameter_string_array.push(`${key}=${oauth_parameter_string_object_ordered[key]}`);
}

// generate parameter string
const oauth_parameter_string = oauth_parameter_string_array.join('&');
const encodedUrl = encodeURIComponent(base_url);
const signature_base_string = `${method}&${encodedUrl}&${encodeURIComponent(oauth_parameter_string)}`
console.log(signature_base_string)
// GET&https%3A%2F%2Fpostman-echo.com%2Foauth1&oauth_consumer_key%3DRKCGzna7bv9YD57c%26oauth_nonce%3De5VR16%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1472121255%26oauth_version%3D1.0
const sign = crypto.createSign('SHA1');
sign.update(signature_base_string);
sign.end();

const oauth_signature = sign.sign(privateKey).toString('base64');
console.log(oauth_signature);
// F9CBjycTpUgOOWk7hSLClpESVs9RB1gXrCrNdol/QsAmrL2HklZTJtRf51aahvpSeYtUJAYDunYiaYEGURB6k0HF82xkZ5kx2AgF+9xRuhMdYR55wNsik59Rm2mSpC/tceKZ7B3AHNHUto/TUn5jghZfdfENhjZEX0WQbQbSURg=

const encoded_oauth_signature = encodeURIComponent(oauth_signature);
console.log(encoded_oauth_signature);
// F9CBjycTpUgOOWk7hSLClpESVs9RB1gXrCrNdol%2FQsAmrL2HklZTJtRf51aahvpSeYtUJAYDunYiaYEGURB6k0HF82xkZ5kx2AgF%2B9xRuhMdYR55wNsik59Rm2mSpC%2FtceKZ7B3AHNHUto%2FTUn5jghZfdfENhjZEX0WQbQbSURg%3D

สามารถเปลี่ยน Algorithm เป็น RSA-SHA1, RSA-SHA256, และ RSA-SHA512 แค่วิธีการคำนวณก็ยังสามารถทำแบบเดิมได้

📄OAuth-1.0-RSA-SHA1.js

ตัวอย่าง Signature ด้วย Algorithm PLAINTEXT

ข้อมูล Authentication ที่จะส่งไปกับ Header จะมีรูปแบบดังนี้

OAuth oauth_consumer_key="RKCGzna7bv9YD57c",
      oauth_signature_method="PLAINTEXT",
      oauth_timestamp="1472121255",
      oauth_nonce="e5VR16",
      oauth_version="1.0",
      oauth_signature="D%252BEdQ-gs%2524-%2525%25402Nu7%26key"

วิธีการคำนวณหา oauth_signature ได้ดังนี้

จำเป็นต้องมีข้อมูลที่ใช้ดังนี้

  • Customer Secret
  • Token Secret
const customerSecret = encodeURIComponent("D+EdQ-gs$-%@2Nu7");
const tokenSecret = 'key'// optional

const signing_key = `${customerSecret}&${tokenSecret}`;

const oauth_signature = signing_key;
console.log(oauth_signature);
// D%2BEdQ-gs%24-%25%402Nu7&key

const encoded_oauth_signature = encodeURIComponent(oauth_signature);
console.log(encoded_oauth_signature);
// D%252BEdQ-gs%2524-%2525%25402Nu7%26key
📄OAuth-1.0-PLAINTEXT.js

OAuth 2.0

oauth2.0 โดยจะแบ่งเป็น Grant Type ได้ 4 ประเภทดังนี้

Authorization code

วิธีส่งข้อมูล Client Authentication จะแบ่งออกเป็น 2 แบบคือ

  • Send as Basic Auth header
  • Send client credentials in body

จำเป็นต้องมีข้อมูลที่ใช้ดังนี้

  • Callback URL
  • Auth URL
  • Access Token URL
  • Client ID
  • Client Secret

โดยจะมีขั้นตอนดังนี้

1. Client ขอสิทธิ์ในการเข้าใช้งาน โดยส่ง client_id และ redirect_uri ในรูปแบบ Query Params ไปกับ Auth URL ดังนี้

GET http://localhost:3000/api/v1/login/oauth/authorize?response_type=code&client_id=test-Client-ID&redirect_uri=https%3A%2F%2Foauth.pstmn.io%2Fv1%2Fcallback

2. โดยจะ redirect ไปยัง https://oauth.pstmn.io/v1/callback และส่ง code ไปด้วย ดังนี้

https://oauth.pstmn.io/v1/callback?code=5YIPSpuhW6ll3wcgY6iE7jPwGds=
oauth-redirect

3. จากนั้นจะส่งข้อมูลต่อไปใน API Access Token URL ดังนี้

- Send as Basic Auth header

โดยจะส่ง Client ID และ Client Secret ให้อยู่ในรูปแบบ Basic auth แล้วไปใน Header ด้วย Key Authorization

const client_id = 'test-Client-ID';
const client_secret = 'test-Client-Secret';

const authBasic = `Basic ${Buffer.from(client_id + ':' + client_secret).toString('base64')}`
console.log(authBasic);
//Basic dGVzdC1DbGllbnQtSUQ6dGVzdC1DbGllbnQtU2VjcmV0

และส่ง Grant Type, Code, Redirect URI และ Client Id ไปใน Body ด้วย Content Type application/x-www-form-urlencoded ดังนี้

{"grant_type":"authorization_code",
"code":"5YIPSpuhW6ll3wcgY6iE7jPwGds=",
"redirect_uri":"https://oauth.pstmn.io/v1/callback",
"client_id":"test-Client-ID"}

- Send client credentials in body

โดยจะส่ง Client ID, Client Secret, Grant Type, Code, Redirect URI ไปใน Body ด้วย Content Type application/x-www-form-urlencoded ดังนี้

{"grant_type":"authorization_code",
"code":"5YIPSpuhW6ll3wcgY6iE7jPwGds=",
"redirect_uri":"https://oauth.pstmn.io/v1/callback",
"client_id":"test-Client-ID",
"client_secret":"test-Client-Secret"}

4. หลังจากการตรวจสิทธิ์การใช้งานแล้วผ่านแล้ว Server จำเป็นต้องส่งอย่างน้อย access_token ให้กับผู้ใช้งาน ตัวอย่าง ดังนี้

{"access_token":"4VfcgzZGZMxAqS/nytLCmHF5qyM=",
"refresh_token":"1Ts5LuZB0zB90zteEq7tMzW7GpA=",
"token_type":"Bearer",
"expires_in":3600,
"scope":""}

Authorization code (with PKCE)

ขั้นตอนคล้ายๆ กับ Authorization code ปกติ แต่จะเพิ่ม Code Challenge Method เป็นแบบ SHA-256 หรือ Plain โดยจะขั้นตอนดังนี้

วิธี่ส่งข้อมูล Client Authentication จะแบ่งออกเป็น 2 แบบคือ

  • Send as Basic Auth header
  • Send client credentials in body

จำเป็นต้องมีข้อมูลที่ใช้ดังนี้

  • Callback URL
  • Auth URL
  • Access Token URL
  • Client ID
  • Client Secret

โดยจะมีขั้นตอนดังนี้

1. Client ขอสิทธิ์ในการเข้าใช้งาน โดยส่ง client_id, redirect_uri, code_challenge และ code_challenge_method ในรูปแบบ Query Params ไปกับ Auth URL ดังนี้

GET http://localhost:3000/api/v1/login/oauth/authorize?response_type=code&client_id=test-Client-ID&redirect_uri=https%3A%2F%2Foauth.pstmn.io%2Fv1%2Fcallback&code_challenge=J_-rkFDpSPSC7vS9Af9U4ka5FczY552BUgy9kR76JEo&code_challenge_method=S256

2. โดยจะ redirect ไปยัง https://oauth.pstmn.io/v1/callback และส่ง code ไปด้วย ดังนี้

https://oauth.pstmn.io/v1/callback?code=5YIPSpuhW6ll3wcgY6iE7jPwGds=
oauth-redirect

3. จากนั้นจะส่งข้อมูลต่อไปใน API Access Token URL ดังนี้

- Send as Basic Auth header

โดยจะส่ง Client ID และ Client Secret ให้อยู่ในรูปแบบ Basic auth แล้วไปใน Header ด้วย Key Authorization

const client_id = 'test-Client-ID';
const client_secret = 'test-Client-Secret';

const authBasic = `Basic ${Buffer.from(client_id + ':' + client_secret).toString('base64')}`
console.log(authBasic);
//Basic dGVzdC1DbGllbnQtSUQ6dGVzdC1DbGllbnQtU2VjcmV0

และส่ง Grant Type, Code, Redirect URI และ Client Id ไปใน Body ด้วย Content Type application/x-www-form-urlencoded ดังนี้

{"grant_type":"authorization_code",
"code":"J97MpZoQKSYoTIIvJSC7xbngAT8=",
"redirect_uri":"https://oauth.pstmn.io/v1/callback",
"code_verifier":"SgvbZcaHrO3jMYxBt27ePypc6Y83amb09Ao6JRrh9UE",
"client_id":"test-Client-ID"}

code_verifier จะถูกสร้างอัตโนมัติหากไม่มีการระบุเอาไว้

- Send client credentials in body

โดยจะส่ง Client ID, Client Secret, Grant Type, Code, Redirect URI และ Code verifier ไปใน Body ด้วย Content Type application/x-www-form-urlencoded ดังนี้

{"grant_type":"authorization_code",
"code":"dsso9aaR8b5ct1T45dg3GsKWWQU=",
"redirect_uri":"https://oauth.pstmn.io/v1/callback",
"code_verifier":"a6yv7V9qEgqS7TmaMZW1jNe-o6uREG8421tM1XBFgCA",
"client_id":"test-Client-ID",
"client_secret":"test-Client-Secret"}

code_verifier จะถูกสร้างอัตโนมัติหากไม่มีการระบุเอาไว้

4. หลังจากการตรวจสิทธิ์การใช้งานแล้วผ่านแล้ว Server จำเป็นต้องส่งอย่างน้อย access_token ให้กับผู้ใช้งาน ตัวอย่าง ดังนี้

{"access_token":"4VfcgzZGZMxAqS/nytLCmHF5qyM=",
"refresh_token":"1Ts5LuZB0zB90zteEq7tMzW7GpA=",
"token_type":"Bearer",
"expires_in":3600,
"scope":""}

Implicit

จำเป็นต้องมีข้อมูลที่ใช้ดังนี้

  • Callback URL
  • Auth URL
  • Client ID

โดยจะมีขั้นตอนดังนี้

1. Auth URL คือ API สำหรับตรวจสอบสิทธิ์และส่งรหัสเข้าใช้งานให้ผู้ใช้งาน

GET http://localhost:3000/login/oauth/authorize

โดยจะส่งข้อมูล Client ID และ Callback URL ในรูปแบบ Query Params ไปกับ Auth URL ดังนี้

http://localhost:3000/login/oauth/authorize?response_type=token&client_id=test-Client-ID&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fapi%2Fv1%2Fregistered%2Fcallback

2. เมื่อ Server ได้ข้อมูลสำหรับตรวจสอบสิทธิ์การใช้งานผ่านแล้ว ก็จะ redirect ไปยัง Callback URL โดยจะส่ง access_token ในรูปแบบ Query Params กลับไปด้วย

GET http://localhost:3000/api/v1/registered/callback?access_token=7ya+OsORA0+wy7Vcpqun0QPiw4E=

Password credentials

วิธี่ส่งข้อมูล Client Authentication จะแบ่งออกเป็น 2 แบบคือ

  • Send as Basic Auth header
  • Send client credentials in body

จำเป็นต้องมีข้อมูลที่ใช้ดังนี้

  • Access Token URL
  • Grant Type
  • Client ID
  • Client Secret
  • Username
  • Password
  • Scope

ตัวอย่าง การใช้งาน Grant Type Password credentials ดังนี้

1. Access Token URL จำต้องมี API สำหรับตรวจสอบสิทธิ์และส่งรหัสเข้าใช้งานให้ผู้ใช้งาน ตัวอย่างดังนี้

POST http://localhost:3000/login/oauth/access_token

//ตามตัวอย่างไม่ได้ระบุว่าต้องเป็น Method POST ให้ allow all method ไว้ก่อนก็ได้นะ

2. ส่งข้อมูลเพิ่อทำการขอ access_token

- Send as Basic Auth header

โดยจะส่ง Client ID และ Client Secret ให้อยู่ในรูปแบบ Basic auth แล้วไปใน Header ด้วย Key Authorization

const client_id = 'test-Client-ID';
const client_secret = 'test-Client-Secret';

const authBasic = `Basic ${Buffer.from(client_id + ':' + client_secret).toString('base64')}`
console.log(authBasic);
//Basic dGVzdC1DbGllbnQtSUQ6dGVzdC1DbGllbnQtU2VjcmV0

และส่ง Grant Type, Username และ Password ไปใน Body ด้วย Content Type application/x-www-form-urlencoded ดังนี้

{"grant_type":"password",
"username":"Username",
"password":"Password"}

- Send client credentials in body

โดยจะส่ง Client ID, Client Secret, Grant Type, Username และ Password ไปใน Body ด้วย Content Type application/x-www-form-urlencoded ดังนี้

{"grant_type":"password",
"username":"Username",
"password":"Password",
"client_id":"test-Client-ID",
"client_secret":"test-Client-Secret"}

3. หลังจากการตรวจสิทธิ์การใช้งานแล้วผ่านแล้ว Server จำเป็นต้องส่งอย่างน้อย access_token ให้กับผู้ใช้งาน ตัวอย่าง ดังนี้

{"access_token":"4VfcgzZGZMxAqS/nytLCmHF5qyM=",
"refresh_token":"1Ts5LuZB0zB90zteEq7tMzW7GpA=",
"token_type":"Bearer",
"expires_in":3600,
"scope":""}

Client credentials

ขั้นตอนคล้ายๆ กับ Password credentials แต่จะไม่มีการส่ง Username และ Password และให้เปลี่ยน grant_type ตอนส่งข้อมูลไปตรวจสอบสิทธิ์การใช้งานจาก password เปลี่ยนเป็น client_credentials

Hawk authentication

ตัวอย่าง ข้อมูล Authentication ที่จะส่งไปกับ Header จะมีรูปแบบดังนี้

Hawk id="dh37fgj492je",
     ts="1669301809",
     nonce="RZKGNz",
     mac="ETCKAQIzJsKGXJSaMzqpe00bsufrzB1g+8IS2Y9cPZM="

วิธีการคำนวณหาเลข mac โดยใช้ขั้นตอนดังนี้

const crypto = require('crypto')

const hawk_auth_id = 'dh37fgj492je';
const hawk_auth_key = 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn';
const method = 'GET';
const nonce = 'RZKGNz';
const timestamp = 1669301809;

//https://postman-echo.com/auth/hawk
const host = 'postman-echo.com';
const resource = '/auth/hawk';
const port = '443'; //example: 80,433
const ext = ''
// request string (newline terminated values):
const hawk_header = `hawk.1.header\n${timestamp}\n${nonce}\n${method}\n${resource}\n${host}\n${port}\n\n${ext}\n`
console.log(hawk_header)

ตัวอย่างข้อมูล header แบบขึ้นบรรทัดใหม่

hawk.1.header
1669301809
RZKGNz
GET
/auth/hawk
postman-echo.com
443


const hmac = crypto.createHmac('sha256', hawk_auth_key);
//passing the data to be hashed
const data = hmac.update(hawk_header);
//Creating the hmac in the required format
const gen_hmac = data.digest('base64');
console.log(gen_hmac)
//ETCKAQIzJsKGXJSaMzqpe00bsufrzB1g+8IS2Y9cPZM=
📄hawk-authentication.js

วิธีการคำนวณหาเลข mac และ มีข้อมูล payload โดยใช้ขั้นตอนดังนี้

const crypto = require('crypto')

const hawk_auth_id = 'dh37fgj492je';
const hawk_auth_key = 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn';
const method = 'GET';
const nonce = 'j4h3g2';
const timestamp = 1669306825;

//https://postman-echo.com/auth/hawk
const host = 'postman-echo.com';
const resource = '/auth/hawk';
const port = '443'; //example: 80,433
const ext = 'some-app-ext-data'

const hawk_payload =`hawk.1.payload
application/json
{prop:"Some Value"}`

console.log(hawk_payload)

const hmac_payload = crypto.createHmac('sha256', hawk_auth_key);
//passing the data to be hashed
const data_payload = hmac_payload.update(hawk_payload);
//Creating the hmac in the required format
const gen_hmac_playload = data_payload.digest('base64');
console.log(gen_hmac_playload)
//rnhCXzcyvQjtrkouE0e6NF12WhvI5xy0dOL9EKQJrZ0=

// request string (newline terminated values):
const hawk_header = `hawk.1.header\n${timestamp}\n${nonce}\n${method}\n${resource}\n${host}\n${port}\n${gen_hmac_playload}\n${ext}\n`
console.log(hawk_header)

const hmac = crypto.createHmac('sha256', hawk_auth_key);
//passing the data to be hashed
data = hmac.update(hawk_header);
//Creating the hmac in the required format
gen_hmac = data.digest('base64');
console.log(gen_hmac)
//TpYOFWAbltqCytxOxevx4pQuFgUo+Vy3G5mGwkDxfVY=
📄hawk-authentication-payload.js

AWS Signature

NTLM authentication

Akamai EdgeGrid

สำหรับ Authentication Type ต่างๆ ของ Postman ก็จะประมาณนี้ครับ ขั้นตอนหลายๆ อย่างอาจจะซับซ่อนไปนิดหน่อยเดี่ยวจะพยายามอธิบายให้ดีกว่านี้นะ