Skip to main content
JWTトークン認証つきの
Web APIを作るのは
Grails+Spring Security
REST Pluginを使えば非常
に簡単である件
JGGUG G*WS LT大会 2016/05/13
Copyright (C) 2016 NTT Software Corporation. All rights reserved.
2
自己紹介
上原潤二(@uehaj)
NTTソフトウェア(株)Grails推進室
JGGUG運営委員
書籍:
プログラミングGROOVY(技評)
Grails徹底入門(翔泳社)
ブログ「Grな日々」
Copyright (C) 2016 NTT Software Corporation. All rights reserved. 3
Web APIの認証をどうする?
• セッション・クッキー
• トークンベース認証 ステートレス
スケーラブル
クロスドメイン
疎結合
Copyright (C) 2016 NTT Software Corporation. All rights reserved. 4
Web APIの認証をどうする?
• セッション・クッキー
• トークンベース認証
– 払い出し方式
– 電子署名方式
• OAuth2.0 アクセストークン
• 上記の簡易版としてのJWTアクセストークン使用
簡単
Copyright (C) 2016 NTT Software Corporation. All rights reserved. 5
JWT(JSON Web Token)
• Webアプリでclaimをうけわたすための仕様
(URL-safe)
• OAuth2.0、OpenID Connectの要素技術
• 実体は電子署名+Base64されたJSON
– Authorization: Bearer eyJhbGciOiJIUzI1….
• アクセストークンにも使用できる
• 利点
– 払い出したトークン値の保存管理が不要
– オフライン検証、第三者による検証
Copyright (C) 2016 NTT Software Corporation. All rights reserved.
Spring Security REST plugin
JWTトークンによ
るAPI認証をデ
フォルトで提供
Copyright (C) 2016 NTT Software Corporation. All rights reserved.
以下の流れ
•まずはRESTサーバを動かす
•Spring Securityの設定
•アクセストークンを取得
•アクセストークンを使ってREST APIア
クセス
7
Copyright (C) 2016 NTT Software Corporation. All rights reserved.
まずはRESTサーバを動かす(1)
$ grails create-app restapp3
| Application created at ../restapp3
$ cd restapp3
$ mkdir -p grails-app/domain/sample
$ cat << EOT > grails-app/domain/sample/Book.groovy
package sample
import grails.rest.*
@Resource
class Book {
String title
int price
}
EOT
8
Copyright (C) 2016 NTT Software Corporation. All rights reserved.
まずはRESTサーバを動かす(2)
URLMapping
grails-app/controllers/restapp3/UrlMappings.groovyに以
下を追加
package restapp3
:
static mappings = {
"/api/books"(resources:"book")
9
Copyright (C) 2016 NTT Software Corporation. All rights reserved.
まずはRESTサーバを動かす(3)
動作確認
$ grails run-app
$ curl http://localhost:8080/api/books.json
[]
$ curl -H "Accept: application/json" -H "Content-type:
application/json" -X POST -d '{"title":"title",
"price":100}' http://localhost:8080/api/books.json
{"class":"sample.Book","id":2,"price":100,"title":"title"}
$ curl http://localhost:8080/api/books.json
[{"class":"sample.Book","id":1,"price":100,"title":"title"}
]
$ curl http://localhost:8080/api/books/1.json
{"class":"sample.Book","id":1,"price":100,"title":"title"}
10
Copyright (C) 2016 NTT Software Corporation. All rights reserved.
Spring Securityの設定(1)
build.gradleのdependenciesに以下を設定
compile "org.grails.plugins:spring-security-core:3.0.3"
compile "org.grails.plugins:spring-security-
rest:2.0.0.M2“
11
Copyright (C) 2016 NTT Software Corporation. All rights reserved.
Spring Securityの設定(2)
$ grails run-app
$ grails s2-quickstart sample User Role
$ cat grails-app/conf/BootStrap.groovy
import sample.*
class BootStrap {
def init = { servletContext ->
def adminRole = new Role('ROLE_ADMIN').save()
def userRole = new Role('ROLE_USER').save()
def testUser = new User('me', 'password').save()
UserRole.create testUser, adminRole
UserRole.withSession { it.flush(); it.clear() }
assert User.count() == 1
assert Role.count() == 2
assert UserRole.count() == 1
}
:
12
ユーザ・ロール情報
をDB登録
Copyright (C) 2016 NTT Software Corporation. All rights reserved.
Spring Securityの設定(3)
grails-app/conf/application.groovy に以下を追加
grails.plugin.springsecurity.userLookup.userDomainClassName
= 'sample.User'
grails.plugin.springsecurity.userLookup.authorityJoinClassName
= 'sample.UserRole'
grails.plugin.springsecurity.authority.className
= 'sample.Role'
grails.plugin.springsecurity.controllerAnnotations.staticRules
= [[pattern:'/**', access:['ROLE_USER', 'ROLE_ADMIN']]]
grails.plugin.springsecurity.filterChain.chainMap
= [[ pattern: '/api/**',
filters: 'JOINED_FILTERS,-anonymousAuthenticationFilter,-
exceptionTranslationFilter,-authenticationProcessingFilter,-
securityContextPersistenceFilter,-rememberMeAuthenticationFilter‘ ],
[ pattern: '/**',
filters: 'JOINED_FILTERS,-restTokenValidationFilter,-
restExceptionTranslationFilter‘ ]]
13
APIを呼ぶ権限
その他の権限
Copyright (C) 2016 NTT Software Corporation. All rights reserved.
アクセストークンを取得
$ curl -H "Accept: application/json" -H "Content-type:
application/json" -X POST -d '{"username":"me",
"password":"password"}' http://localhost:8080/api/login
{"username":"me","roles":["ROLE_ADMIN"],"token_typ
e":"Bearer","access_token":"eyJhbGciOiJIUzI1…","e
xpires_in":3600,"refresh_token":"eyJhbGc…"}
14
認証エンドポイント
アクセストークン
(JWT)
リフレッシュトークン
(JWT)
Copyright (C) 2016 NTT Software Corporation. All rights reserved.
アクセストークンを使ってREST API
アクセス
$ curl -H “Accept: application/json” -H “Content-type:
application/json” -H “Authorization: Bearer
eyJhbGciOiJIUzI1…." -X GET
http://localhost:8080/api/books.json
[{"id":1,"price":100,"title":"Book Title"}]
15
Copyright (C) 2016 NTT Software Corporation. All rights reserved.
まとめ
• GrailsでのREST API開発は超簡単
• JWT便利。メール認証などにも。
• トークン無効化が不要ならシンプル
• トークン無効化するにはexpire期限を指定しリ
フレッシュトークンで再発行
– http://stackoverflow.com/questions/196559
11/request-new-access-token-using-
refresh-token-in-username-password-grant-
in-sprin
16
Copyright (C) 2016 NTT Software Corporation. All rights reserved.
参考リンク
• Grails3対応のSpring Securty RESTドキュメント
http://alvarosanchez.github.io/grails-spring-security-
rest/latest/docs/
• Grails2対応のSpring Securty RESTドキュメント
http://alvarosanchez.github.io/grails-spring-security-
rest/1.5.3/docs/guide/index.html
• Grails 3でWeb APIを簡単に作ろう!
https://speakerdeck.com/yamkazu/grails-3deweb-
apiwojian-dan-nizuo-rou
17