#はじめに
Client Credentials Grantと、Resource Owner Password Credentials Grantが再現出来たので、Introspectも再現しようと思います。
https://qiita.com/namikitakeo/items/38be899790cb27a323df
#つくる
Introspectコントローラーを作成します。
http://localhost:5000/op/introspect
Controllers/IntrospectController.cs
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using myop.Models;
namespace myop.Controllers
{
public class Introspect
{
public bool active { get; set; }
public string scope { get; set; }
public int? exp { get; set; }
public int? iat { get; set; }
public string sub { get; set; }
public string aud { get; set; }
public string iss { get; set; }
}
[Route("op/[controller]")]
[ApiController]
public class IntrospectController : ControllerBase
{
private readonly ApplicationDbContext _context;
string CLIENT_ID;
string CLIENT_SECRET;
string TOKEN;
public IntrospectController(ApplicationDbContext context)
{
_context = context;
}
// POST: op/introspect
[HttpPost]
public async Task<ActionResult<Introspect>> doPost()
{
string body = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync();
string[] p = body.Split('&');
for (int i=0; i<p.Length; i++){
string[] values = p[i].Split('=');
switch(values[0])
{
case "client_id":CLIENT_ID=values[1];break;
case "client_secret":CLIENT_SECRET=values[1];break;
case "token":TOKEN=values[1];break;
}
}
string ISS = "http://localhost:5000/op";
string SCOPE = null;
string SUB = null;
string AUD = CLIENT_ID;
int IAT = 0;
bool ACTIVE = false;
var client = await _context.Clients.FindAsync(CLIENT_ID);
if (client == null) {
return new Introspect {active = ACTIVE, iss = ISS};
}
if (client.AccessType == "confidential") {
if (client.ClientSecret != CLIENT_SECRET) return new Introspect {active = ACTIVE, iss = ISS};
} else if (client.AccessType == "public") {
if (client.GrantTypes != "password" && client.GrantTypes != "authorization_code" && client.GrantTypes != "implicit") return new Introspect {active = ACTIVE, iss = ISS};
if (CLIENT_SECRET != null) return new Introspect {active = ACTIVE, iss = ISS};
} else {
return new Introspect {active = ACTIVE, iss = ISS};
}
var token = await _context.Tokens.FirstOrDefaultAsync(e => e.AccessToken == TOKEN);
if (token != null) {
if (CLIENT_ID == token.ClientId) {
SCOPE = token.Scope;
SUB = token.UserId;
int unixTimestamp = (int)(DateTime.Now.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
IAT = (int)(token.Iat.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
if (unixTimestamp - IAT < 60) ACTIVE = true;
} else {
IAT=0;
}
}
if (IAT==0) {
return new Introspect {active = ACTIVE, iss = ISS};
} else {
return new Introspect {active = ACTIVE, scope = SCOPE, exp = IAT + 60, iat = IAT, sub = SUB, aud = AUD, iss = ISS};
}
}
}
}
期限切れのTOKEN
$ curl -d "client_id=client2&token=5CCC70961A514EA9A95B195E99B4B754" http://localhost:5000/op/introspect
{"active":false,"scope":"openid","exp":1584998144,"iat":1584998084,"sub":"user01","aud":"client1","iss":"http://localhost:5000"}
期限内のTOKEN
$ curl -d "client_id=client2&grant_type=password&username=user01&password=user01" http://localhost:5000/op/token
{"access_token":"CC8B08A746FC445A98320C7580AB5972","refresh_token":"DD8B08A746FC445A98320C7580AB5972","expires_in":60,"token_type":"bearer","scope":"openid"}
$ curl -d "client_id=client2&token=CC8B08A746FC445A98320C7580AB5972" http://localhost:5000/op/intro
spect
{"active":true,"scope":"openid","exp":1584998352,"iat":1584998292,"sub":"user01","aud":"client1","iss":"http://localhost:5000"}
知らないTOKEN
$ curl -d "client_id=client2&token=CC8B08A746FC445A98320C7580AB592" http://localhost:5000/op/intros
pect
{"active":false,"iss":"http://localhost:5000"}
制限事項
- access_tokenの有効期限は60秒固定で、1ユーザーにつき1つの制限があります。
#次回
つくるオーオース Authorization Code Grant編
https://qiita.com/namikitakeo/items/b41d66fe88ab563bd13a