つくるオーオース　Discovery編

#はじめに
Authorization Code Grantと、Implicit Grantと、Client Credentials Grantと、Resource Owner Password Credentials Grantが再現出来たので、Discoveryも再現しようと思います。

#つくる
Discoveryコントローラーを作成します。
http://localhost:5000/op/.well-known/openid-configuration

```C#:Controllers/DiscoveryController.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 Discovery
    {
        public string issuer { get; set; }
        public string[] grant_types_supported { get; set; }
        public string[] response_types_supported { get; set; }
        public string authorization_endpoint { get; set; }
        public string token_endpoint { get; set; }
        public string introspection_endpoint { get; set; }
        public string jwks_uri { get; set; }
    }

    [Route("op/.well-known/openid-configuration")]
    [ApiController]
    public class DiscoveryController : ControllerBase
    {
        private readonly ApplicationDbContext _context;
        public DiscoveryController(ApplicationDbContext context)
        {
            _context = context;
        }

        // GET: op/.well-known/openid-configuration
        [HttpGet]
        public async Task<ActionResult<Discovery>> doGet()
        {
            Discovery discovery = new Discovery {issuer = "http://localhost:5000/op", grant_types_supported = new string[] {"authorization_code","implicit","client_credentials","password","refresh_token"}, response_types_supported = new string[] {"code","id_token","token id_token"}, authorization_endpoint = "http://localhost:5000/op/auth", token_endpoint = "http://localhost:5000/op/token", introspection_endpoint = "http://localhost:5000/op/introspect", jwks_uri = "http://localhost:5000/op/keys"};
            await _context.SaveChangesAsync();
            return discovery;
        }
    }
}
```

Keysコントローラーも作成します。
http://localhost:5000/op/keys

```C#:Controllers/KeysController.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 Key
    {
        public string kty { get; set; }
        public string kid { get; set; }
        public string use { get; set; }
        public string alg { get; set; }
        public string n { get; set; }
        public string e { get; set; }
    }
    public class Keys
    {
        public Key[] keys { get; set; }
    }

    [Route("op/keys")]
    [ApiController]
    public class KeysController : ControllerBase
    {
        private readonly ApplicationDbContext _context;
        public KeysController(ApplicationDbContext context)
        {
            _context = context;
        }

        // GET: op/keys
        [HttpGet]
        public async Task<ActionResult<Keys>> doGet()
        {
            Key key = new Key {kty = "RSA", kid = "testkey", use = "sig", alg = "RS256", n = "68AgRr2w3WutTMV0k8AK076qtQamauVhRvKcyRrT8GP7FQIJTRLnunmmwR78PC4R868GnfoW54l3FX-DAywtuS1NVrKZpsDDF5bBBD9-k2y8gJfALvVV6RIVsHmWMeulMb6o9OVDC4HktBSJGpaFy2kKNhde5PaWhnoq5lCjnLSCEbfZxTVrTFAaF3Mr4Thww5xm7lnSICYotDycTIe8C5ErsBhJFNX82V40pO8TNU2IDY7Zf_fpsUzI6eOoAxKBY7nUOX8bKf5WMo3-ztYCLoN4Oaf9xmjWT-zjEnsozIctAQ_JjZcofEhqLTKjsVvRIoweUqP9EBfsHn7UkJSTCQ", e = "AQAB"};
            Keys keys = new Keys {keys = new Key[] {key}};
            await _context.SaveChangesAsync();
            return keys;
        }
    }
}
```

動作確認してみます。

```
$ curl http://localhost:5000/op/.well-known/openid-configuration

{"issuer":"http://localhost:5000/op","grant_types_supported":["authorization_code","implicit","client_credentials","password","refresh_token"],"response_types_supported":["code"],"authorization_endpoint":"http://localhost:5000/op/auth","token_endpoint":"http://localhost:5000/op/token","introspection_endpoint":"http://localhost:5000/op/introspect","jwks_uri":"http://localhost:5000/op/keys"}

$ curl http://localhost:5000/op/keys

{"keys":[{"kty":"RSA","kid":"public.key","use":"sig","alg":"RS256","n":"AJ56Fm5BN0rQqvRLUGhR6IBjNZWiXRpQ5FVFSgBizmQtD1wNGqjOeK0jKLtE-oTGXSbUTCkTzH1HUQcZwJJ79wGmhC04lPVUnQ0SwQl-K63mm0GgrTgZDHv55MOf_eB832Gu39iJ2QvjjGwNVgAbb3aU4V6f6KFTu6cZtKO9WHCWwbEV4VoSNJOFZyZUl-GoxC86o66PcckePzsjstjHaDtNU7zidJiKT0bZ0WtcQLbzxOY2e1KOLDCUkUmD3c-XSIREWVvpMNszNWQ9w6HkxUkCls71g_aumW7WlDCI8AkAcsJxh7nPZKJFBRMAeA2MqtbebEq3KUZVlax675R3Ouk","e":"AQAB"}]}
```

#参考
OpenID ConnectのJWTとJWKを手軽につくりたい
https://qiita.com/shu-yusa/items/36855cf1e9b4ec2adf28

```
$ openssl genrsa 2048 > private.pem
$ openssl rsa -in private.pem -pubout -out public.pem
$ npm install -g pem-jwk
$ pem-jwk public.pem
```