概要

I had the opportunity to test IIIF Authentication API 2.0, so here are my notes.

https://iiif.io/api/auth/2.0/

I created the following demo site.

https://iiif-auth-nextjs.vercel.app/ja

The repository is as follows.

https://github.com/nakamura196/iiif-auth-nextjs

Below is an AI-generated explanation. Note that I was unable to get it working properly with Mirador, which remains a future task.

概要

This article provides a detailed explanation of the IIIF Authentication API 2.0 authentication flow at the level of actual HTTP requests/responses. We will trace what requests are sent and what responses are returned at each step.

Architecture Overview

(CBlrioewnster)IIIFServerAuthService

Authentication Flow Details

Step 1: Initial Image Information Request (Unauthenticated)

Request:

GHAEocTscte/:patpl:icaiapilpihlfiscitam:ta3ig0oe0n/1/sjasmopnle/info.jsonHTTP/1.1

Processing Flow (Server-side):

e}xpcli}ci}aoefofprnttnr}pt1s2(o3s4(e,/.tt.!k.t.!tes}aaoteiure]{psCakAonTiRsrrr"""iyhuelkoseVnov@its/netnse=kVtaricdyticchoneaulN:co"paikH=)rnlrieen:etifeceindx':t"ufuAaah{qvd)tAe`:s/nudueue4Ru[x$:ictetcer=0{et{t{"mthrhksi1sh"rA4aioHtftpe:eu0gor=eq.ioionqt1eniaunckfnt"uh/zrdeeaesiheP}[Gaeerxtnuectsr)iEtqrytin.atto;dTiu?Uo?ajtp.b](oe.prnusi:ne/rnsralatoo/eSieter.whnn/xenqh.pasae(itrfuehlmein{riUvoeaeaeatteiri.sdactriqflcjtedeecvcu..es:re(rheaiio2or'sPrtror"nNsBaiee/i/e.e(rfddagrxgafay'pioteramT,inuRtelso/}te(rl.ka/eq'bgeua.ua'aentpteu,ct(hisstk(t//th)'o2i)otk/ir)oeci{i;knofze)n/antpt':eri)xoontbnu.e'lj`)ls,;;o'n;",

Response:

HCA{}TocTnc""}Ptees]/esre"""1nsrr@it.t-ovcdy1-Crio"pTo"cn:e4yn:et"0pt"e":1er":xh:oAtt"Ulu["tAna-t{:puapAh:tuple"/htllnh/Phiottlrocwitoora-cpcbitOa:aezirt/lSeoii/hedngoior/inisvjnitis:rf:coe.3enqi02uo0"i/1ra/epadip"/i,a/uitihi/f2pcroonbtee"x,t.json",

Step 2: Request to Probe Service

The client obtains the AuthProbeService2 URL from the 401 response and checks the authentication status.

Request:

GHAEocTscte/:patpl:icaiapilpihlfiscptar:to3ib0oe0n1/HjTsToPn/1.1

Processing Flow (Server-side):

e}xpcci}r}aooofe,prnnci}t""""}ptss(ofIu@tss]{/tttnr}frcyte""""""}aaos(e)nopar@itpls]spsatktpt""""};unetvcdyrae"""tiyuoeaIu@tslnNt"uio"pobr@ita/ntknpyfrcyto""aee:scn:efevcdytiche)alnopacituxx"et"ilio"puiHnyoanetadyttt":"e`:l"cn:esife{lauNt"ut"phR"A:x$e:et":fua=odtee:si:eee:u4t{"""e`:/nda)hxx"o"nst0["rA:":x$4pceadett":n`:tp"h1{:euLt{"0rtru{nR"A"$iohP,qt"o["rA1oit=te:u2:{"cntr"uhag{:eubo=hist0rIastoheAciqt}enHacp"h0{emtepbtsctn"uh)/rewaohP,qae.:ettciheA;rGeaatntrugdj/Rp.evttscoEqdiestoeese:nseottcuTuetdepbs"is/es"p.et(er.:etniu/xS,I:nsers?vj/R.(iliteI/es.et.esen{ftiUrI/xTtq.rrise.2irvFitosuheiniuxi"fliiUkeepf(ilto,..cAiresaly{ftU/ioeuflntdaT.2raor2t..S:ecoi"lp/i"hioereko,.iag,orrNs(e/o/piD/ive.'naraineagixgB(piu/}mpicteetigta/oineRtao/ihua"/}2e(rkan/tp,a/"q'eeu}2hiuauarnt////tpeu)hac2ihist';/po/i//th,2inci2i)o//tof/ircien/ci{ioixtaofz)nitecn/a;tf.xcttte/jteeoixis.sxkotmojsten.ans`.n'jg"o,j`)se,ns,;o/"ons,n"a",m,ple/info.json`,

Response (Unauthenticated):

{}""""}@tss]cyte""""""}opar@itpls]netvcdyrae"""t"uio"pobr@ite:scn:efevcdyx"et"ilio"pt":"e":l"cn:e"A:xhe:et":u4tt"""e":t0["tA:":xh"h1{:puLtt"hP,:t"o["tAtr"/hag{:putoh/Aci:tpbtlctn"/h:etocih/A/Rpcevttlc/e:aseotocis/ls"pceiu/hS,I:asilioeI/lsftisrI/hT.2itvFiooi"f:iisko,.3cAite/i0euf:nao02t.3Sp/1"hi0eia/,o0r/paD/1aipea/iu/impacta/oipehui"/i2/ti,a/"2hiui//ftic2hioa/fncc2toctenecoxtsoktesne.x"tnjt,e"s.x,ojtns."oj,ns"o,n",

Step 3: Starting the Authentication Window

The client obtains the AuthAccessTokenService2 URL from the Probe Service response and opens a popup window.

Client-side Processing:

ccccttc)ooooooo;nnnnkknt''GssGsBseeOsoiwettetutnnptkiitniUUeeidatemltrrnanftauoredolluU-hutkask..ptra=thetstessohlu6hSneaoneepW.t0eeSgkUaauith0nremeerrrpno',tvreInlccdS,hiivsdhhwotecciss=PPiwriaeca=eaanigtegrnrrd=nhi=ecveaaogto=riwmmww(=npIycssi)6raDpeU..n,0soutRssd0ebt(oULeeo'rehf.R(ttwvRSorLt((.ieerao''ocsrnkmopeuvrdeerelieonsinitcsmSsg(n.epUeaifs.oUrgnoesnIve'rresDiI,mvre(cdaiv)e'wtcii;.,iiecdino[eedmdn0[n)eo]0t;sw;]is.;faligocecaIatdti)io;onn).origin);

Generated URL:

http://localhost:3001/api/iiif/token?messageId=60f4420d-52c1-48ae-a24f-c3bb948fa0dc&origin=http://localhost:3001

Step 4: Token Service Redirect Processing

Request:

GHEoTst/:apliciailihfstto:k3e0n0?1messageId=60f4420d-52c1-48ae-a24f-c3bb948fa0dc&origin=http://localhost:3001HTTP/1.1

Processing Flow (Server-side):

GHAEocTscte/:patpl:icaiapilpihlfiscitam:ta3ig0oe0n/1/sjasmopnle/info.jsonHTTP/1.1

0

Response:

GHAEocTscte/:patpl:icaiapilpihlfiscitam:ta3ig0oe0n/1/sjasmopnle/info.jsonHTTP/1.1

1

Step 5: Authentication on the Login Page

Login Form Submission:

GHAEocTscte/:patpl:icaiapilpihlfiscitam:ta3ig0oe0n/1/sjasmopnle/info.jsonHTTP/1.1

2

Processing Flow (Server-side):

GHAEocTscte/:patpl:icaiapilpihlfiscitam:ta3ig0oe0n/1/sjasmopnle/info.jsonHTTP/1.1

3

JWT Generation Details:

GHAEocTscte/:patpl:icaiapilpihlfiscitam:ta3ig0oe0n/1/sjasmopnle/info.jsonHTTP/1.1

4

Response:

GHAEocTscte/:patpl:icaiapilpihlfiscitam:ta3ig0oe0n/1/sjasmopnle/info.jsonHTTP/1.1

5

Step 6: Token Delivery (postMessage)

After successful login, the client receives the token and sends it to the original window via the Token Service.

Client-side (auth/page.tsx):

GHAEocTscte/:patpl:icaiapilpihlfiscitam:ta3ig0oe0n/1/sjasmopnle/info.jsonHTTP/1.1

6

Step 7: Token Reception in the Original Window

Client-side (Main Window):

GHAEocTscte/:patpl:icaiapilpihlfiscitam:ta3ig0oe0n/1/sjasmopnle/info.jsonHTTP/1.1

7

Step 8: Authenticated Image Request

Request:

GHAEocTscte/:patpl:icaiapilpihlfiscitam:ta3ig0oe0n/1/sjasmopnle/info.jsonHTTP/1.1

8

Processing Flow (Server-side):

GHAEocTscte/:patpl:icaiapilpihlfiscitam:ta3ig0oe0n/1/sjasmopnle/info.jsonHTTP/1.1

9

Response:

e}xpcli}ci}aoefofprnttnr}pt1s2(o3s4(e,/.tt.!k.t.!tes}aaoteiure]{psCakAonTiRsrrr"""iyhuelkoseVnov@its/netnse=kVtaricdyticchoneaulN:co"paikH=)rnlrieen:etifeceindx':t"ufuAaah{qvd)tAe`:s/nudueue4Ru[x$:ictetcer=0{et{t{"mthrhksi1sh"rA4aioHtftpe:eu0gor=eq.ioionqt1eniaunckfnt"uh/zrdeeaesiheP}[Gaeerxtnuectsr)iEtqrytin.atto;dTiu?Uo?ajtp.b](oe.prnusi:ne/rnsralatoo/eSieter.whnn/xenqh.pasae(itrfuehlmein{riUvoeaeaeatteiri.sdactriqflcjtedeecvcu..es:re(rheaiio2or'sPrtror"nNsBaiee/i/e.e(rfddagrxgafay'pioteramT,inuRtelso/}te(rl.ka/eq'bgeua.ua'aentpteu,ct(hisstk(t//th)'o2i)otk/ir)oeci{i;knofze)n/antpt':eri)xoontbnu.e'lj`)ls,;;o'n;",

0

Token Persistence and Synchronization

Persistence via localStorage

e}xpcli}ci}aoefofprnttnr}pt1s2(o3s4(e,/.tt.!k.t.!tes}aaoteiure]{psCakAonTiRsrrr"""iyhuelkoseVnov@its/netnse=kVtaricdyticchoneaulN:co"paikH=)rnlrieen:etifeceindx':t"ufuAaah{qvd)tAe`:s/nudueue4Ru[x$:ictetcer=0{et{t{"mthrhksi1sh"rA4aioHtftpe:eu0gor=eq.ioionqt1eniaunckfnt"uh/zrdeeaesiheP}[Gaeerxtnuectsr)iEtqrytin.atto;dTiu?Uo?ajtp.b](oe.prnusi:ne/rnsralatoo/eSieter.whnn/xenqh.pasae(itrfuehlmein{riUvoeaeaeatteiri.sdactriqflcjtedeecvcu..es:re(rheaiio2or'sPrtror"nNsBaiee/i/e.e(rfddagrxgafay'pioteramT,inuRtelso/}te(rl.ka/eq'bgeua.ua'aentpteu,ct(hisstk(t//th)'o2i)otk/ir)oeci{i;knofze)n/antpt':eri)xoontbnu.e'lj`)ls,;;o'n;",

1

Synchronization Between Tabs

e}xpcli}ci}aoefofprnttnr}pt1s2(o3s4(e,/.tt.!k.t.!tes}aaoteiure]{psCakAonTiRsrrr"""iyhuelkoseVnov@its/netnse=kVtaricdyticchoneaulN:co"paikH=)rnlrieen:etifeceindx':t"ufuAaah{qvd)tAe`:s/nudueue4Ru[x$:ictetcer=0{et{t{"mthrhksi1sh"rA4aioHtftpe:eu0gor=eq.ioionqt1eniaunckfnt"uh/zrdeeaesiheP}[Gaeerxtnuectsr)iEtqrytin.atto;dTiu?Uo?ajtp.b](oe.prnusi:ne/rnsralatoo/eSieter.whnn/xenqh.pasae(itrfuehlmein{riUvoeaeaeatteiri.sdactriqflcjtedeecvcu..es:re(rheaiio2or'sPrtror"nNsBaiee/i/e.e(rfddagrxgafay'pioteramT,inuRtelso/}te(rl.ka/eq'bgeua.ua'aentpteu,ct(hisstk(t//th)'o2i)otk/ir)oeci{i;knofze)n/antpt':eri)xoontbnu.e'lj`)ls,;;o'n;",

2

CORS Configuration

Image API Endpoint

e}xpcli}ci}aoefofprnttnr}pt1s2(o3s4(e,/.tt.!k.t.!tes}aaoteiure]{psCakAonTiRsrrr"""iyhuelkoseVnov@its/netnse=kVtaricdyticchoneaulN:co"paikH=)rnlrieen:etifeceindx':t"ufuAaah{qvd)tAe`:s/nudueue4Ru[x$:ictetcer=0{et{t{"mthrhksi1sh"rA4aioHtftpe:eu0gor=eq.ioionqt1eniaunckfnt"uh/zrdeeaesiheP}[Gaeerxtnuectsr)iEtqrytin.atto;dTiu?Uo?ajtp.b](oe.prnusi:ne/rnsralatoo/eSieter.whnn/xenqh.pasae(itrfuehlmein{riUvoeaeaeatteiri.sdactriqflcjtedeecvcu..es:re(rheaiio2or'sPrtror"nNsBaiee/i/e.e(rfddagrxgafay'pioteramT,inuRtelso/}te(rl.ka/eq'bgeua.ua'aentpteu,ct(hisstk(t//th)'o2i)otk/ir)oeci{i;knofze)n/antpt':eri)xoontbnu.e'lj`)ls,;;o'n;",

3

Probe/Access Service

e}xpcli}ci}aoefofprnttnr}pt1s2(o3s4(e,/.tt.!k.t.!tes}aaoteiure]{psCakAonTiRsrrr"""iyhuelkoseVnov@its/netnse=kVtaricdyticchoneaulN:co"paikH=)rnlrieen:etifeceindx':t"ufuAaah{qvd)tAe`:s/nudueue4Ru[x$:ictetcer=0{et{t{"mthrhksi1sh"rA4aioHtftpe:eu0gor=eq.ioionqt1eniaunckfnt"uh/zrdeeaesiheP}[Gaeerxtnuectsr)iEtqrytin.atto;dTiu?Uo?ajtp.b](oe.prnusi:ne/rnsralatoo/eSieter.whnn/xenqh.pasae(itrfuehlmein{riUvoeaeaeatteiri.sdactriqflcjtedeecvcu..es:re(rheaiio2or'sPrtror"nNsBaiee/i/e.e(rfddagrxgafay'pioteramT,inuRtelso/}te(rl.ka/eq'bgeua.ua'aentpteu,ct(hisstk(t//th)'o2i)otk/ir)oeci{i;knofze)n/antpt':eri)xoontbnu.e'lj`)ls,;;o'n;",

4

Error Handling

Token Expiration

e}xpcli}ci}aoefofprnttnr}pt1s2(o3s4(e,/.tt.!k.t.!tes}aaoteiure]{psCakAonTiRsrrr"""iyhuelkoseVnov@its/netnse=kVtaricdyticchoneaulN:co"paikH=)rnlrieen:etifeceindx':t"ufuAaah{qvd)tAe`:s/nudueue4Ru[x$:ictetcer=0{et{t{"mthrhksi1sh"rA4aioHtftpe:eu0gor=eq.ioionqt1eniaunckfnt"uh/zrdeeaesiheP}[Gaeerxtnuectsr)iEtqrytin.atto;dTiu?Uo?ajtp.b](oe.prnusi:ne/rnsralatoo/eSieter.whnn/xenqh.pasae(itrfuehlmein{riUvoeaeaeatteiri.sdactriqflcjtedeecvcu..es:re(rheaiio2or'sPrtror"nNsBaiee/i/e.e(rfddagrxgafay'pioteramT,inuRtelso/}te(rl.ka/eq'bgeua.ua'aentpteu,ct(hisstk(t//th)'o2i)otk/ir)oeci{i;knofze)n/antpt':eri)xoontbnu.e'lj`)ls,;;o'n;",

5

Handling Authentication Errors

e}xpcli}ci}aoefofprnttnr}pt1s2(o3s4(e,/.tt.!k.t.!tes}aaoteiure]{psCakAonTiRsrrr"""iyhuelkoseVnov@its/netnse=kVtaricdyticchoneaulN:co"paikH=)rnlrieen:etifeceindx':t"ufuAaah{qvd)tAe`:s/nudueue4Ru[x$:ictetcer=0{et{t{"mthrhksi1sh"rA4aioHtftpe:eu0gor=eq.ioionqt1eniaunckfnt"uh/zrdeeaesiheP}[Gaeerxtnuectsr)iEtqrytin.atto;dTiu?Uo?ajtp.b](oe.prnusi:ne/rnsralatoo/eSieter.whnn/xenqh.pasae(itrfuehlmein{riUvoeaeaeatteiri.sdactriqflcjtedeecvcu..es:re(rheaiio2or'sPrtror"nNsBaiee/i/e.e(rfddagrxgafay'pioteramT,inuRtelso/}te(rl.ka/eq'bgeua.ua'aentpteu,ct(hisstk(t//th)'o2i)otk/ir)oeci{i;knofze)n/antpt':eri)xoontbnu.e'lj`)ls,;;o'n;",

6

Security Considerations

1. Token Signature Verification

e}xpcli}ci}aoefofprnttnr}pt1s2(o3s4(e,/.tt.!k.t.!tes}aaoteiure]{psCakAonTiRsrrr"""iyhuelkoseVnov@its/netnse=kVtaricdyticchoneaulN:co"paikH=)rnlrieen:etifeceindx':t"ufuAaah{qvd)tAe`:s/nudueue4Ru[x$:ictetcer=0{et{t{"mthrhksi1sh"rA4aioHtftpe:eu0gor=eq.ioionqt1eniaunckfnt"uh/zrdeeaesiheP}[Gaeerxtnuectsr)iEtqrytin.atto;dTiu?Uo?ajtp.b](oe.prnusi:ne/rnsralatoo/eSieter.whnn/xenqh.pasae(itrfuehlmein{riUvoeaeaeatteiri.sdactriqflcjtedeecvcu..es:re(rheaiio2or'sPrtror"nNsBaiee/i/e.e(rfddagrxgafay'pioteramT,inuRtelso/}te(rl.ka/eq'bgeua.ua'aentpteu,ct(hisstk(t//th)'o2i)otk/ir)oeci{i;knofze)n/antpt':eri)xoontbnu.e'lj`)ls,;;o'n;",

7

2. Using HTTPS (Production Environment)

e}xpcli}ci}aoefofprnttnr}pt1s2(o3s4(e,/.tt.!k.t.!tes}aaoteiure]{psCakAonTiRsrrr"""iyhuelkoseVnov@its/netnse=kVtaricdyticchoneaulN:co"paikH=)rnlrieen:etifeceindx':t"ufuAaah{qvd)tAe`:s/nudueue4Ru[x$:ictetcer=0{et{t{"mthrhksi1sh"rA4aioHtftpe:eu0gor=eq.ioionqt1eniaunckfnt"uh/zrdeeaesiheP}[Gaeerxtnuectsr)iEtqrytin.atto;dTiu?Uo?ajtp.b](oe.prnusi:ne/rnsralatoo/eSieter.whnn/xenqh.pasae(itrfuehlmein{riUvoeaeaeatteiri.sdactriqflcjtedeecvcu..es:re(rheaiio2or'sPrtror"nNsBaiee/i/e.e(rfddagrxgafay'pioteramT,inuRtelso/}te(rl.ka/eq'bgeua.ua'aentpteu,ct(hisstk(t//th)'o2i)otk/ir)oeci{i;knofze)n/antpt':eri)xoontbnu.e'lj`)ls,;;o'n;",

8

3. Origin Verification

e}xpcli}ci}aoefofprnttnr}pt1s2(o3s4(e,/.tt.!k.t.!tes}aaoteiure]{psCakAonTiRsrrr"""iyhuelkoseVnov@its/netnse=kVtaricdyticchoneaulN:co"paikH=)rnlrieen:etifeceindx':t"ufuAaah{qvd)tAe`:s/nudueue4Ru[x$:ictetcer=0{et{t{"mthrhksi1sh"rA4aioHtftpe:eu0gor=eq.ioionqt1eniaunckfnt"uh/zrdeeaesiheP}[Gaeerxtnuectsr)iEtqrytin.atto;dTiu?Uo?ajtp.b](oe.prnusi:ne/rnsralatoo/eSieter.whnn/xenqh.pasae(itrfuehlmein{riUvoeaeaeatteiri.sdactriqflcjtedeecvcu..es:re(rheaiio2or'sPrtror"nNsBaiee/i/e.e(rfddagrxgafay'pioteramT,inuRtelso/}te(rl.ka/eq'bgeua.ua'aentpteu,ct(hisstk(t//th)'o2i)otk/ir)oeci{i;knofze)n/antpt':eri)xoontbnu.e'lj`)ls,;;o'n;",

9

Performance Optimization

1. Token Caching

HCA{}TocTnc""}Ptees]/esre"""1nsrr@it.t-ovcdy1-Crio"pTo"cn:e4yn:et"0pt"e":1er":xh:oAtt"Ulu["tAna-t{:puapAh:tuple"/htllnh/Phiottlrocwitoora-cpcbitOa:aezirt/lSeoii/hedngoior/inisvjnitis:rf:coe.3enqi02uo0"i/1ra/epadip"/i,a/uitihi/f2pcroonbtee"x,t.json",

0

2. Handling Parallel Requests

HCA{}TocTnc""}Ptees]/esre"""1nsrr@it.t-ovcdy1-Crio"pTo"cn:e4yn:et"0pt"e":1er":xh:oAtt"Ulu["tAna-t{:puapAh:tuple"/htllnh/Phiottlrocwitoora-cpcbitOa:aezirt/lSeoii/hedngoior/inisvjnitis:rf:coe.3enqi02uo0"i/1ra/epadip"/i,a/uitihi/f2pcroonbtee"x,t.json",

1

Troubleshooting

1. Popup Blocker

HCA{}TocTnc""}Ptees]/esre"""1nsrr@it.t-ovcdy1-Crio"pTo"cn:e4yn:et"0pt"e":1er":xh:oAtt"Ulu["tAna-t{:puapAh:tuple"/htllnh/Phiottlrocwitoora-cpcbitOa:aezirt/lSeoii/hedngoior/inisvjnitis:rf:coe.3enqi02uo0"i/1ra/epadip"/i,a/uitihi/f2pcroonbtee"x,t.json",

2

2. postMessage Reception Failure

HCA{}TocTnc""}Ptees]/esre"""1nsrr@it.t-ovcdy1-Crio"pTo"cn:e4yn:et"0pt"e":1er":xh:oAtt"Ulu["tAna-t{:puapAh:tuple"/htllnh/Phiottlrocwitoora-cpcbitOa:aezirt/lSeoii/hedngoior/inisvjnitis:rf:coe.3enqi02uo0"i/1ra/epadip"/i,a/uitihi/f2pcroonbtee"x,t.json",

3

まとめ

In the IIIF Authentication API 2.0 implementation, requests are processed in the following flow:

  1. Initial Access → 401 with Probe Service
  2. Probe Service → 401 with Access Service
  3. Token Service → Login Page redirect
  4. Login → JWT Token generation
  5. postMessage → Token delivery to main window
  6. Authenticated Request → Protected resource access

By implementing proper error handling and security measures at each step, you can build a safe and user-friendly authentication system.

References