Auth0 + React-Routerで認証を楽にこなそうとしているが楽ではない。
SPAで認証をしようとすると。Webベースのリダイレクトガンガンの
ような認証ができないしなぁと思っていたら。
そういう要望に応えたのがOAuth2というものということらしい。
Auth0という認証サービスが便利らしいので試してみる。
React+ auth0
React+auth0のサンプルは以下にあり。auth0のcallbackの
設定を「http://localhost:3000/index.html」とすると動作しました。
React-Router + auth0
さて、次にReact-Routerと組み合わせて使ってみます。
npmパッケージをインストール!
npm install auth0-lock --save cd node_modules cd auth0-lock npm install ejsify npm install packageify npm install brfs
react-routerを使っているので・・
こんなかんじですべてのコンポーネントにlockプロパティを設定する。
import Auth0Variables from 'auth0-variables' import Auth0Lock from 'auth0-lock' const history = createHistory() function createElement(Component, props) { props.lock = new Auth0Lock(Auth0Variables.AUTH0_CLIENT_ID, Auth0Variables.AUTH0_DOMAIN); return <Component {...props} /> } React.render(( <Router history={history} createElement={createElement}> <Route path="/" component={App}> <Route path="/home" component={Home} /> <Route path="/login" component={Login} /> <Route path="/logout" component={Logout} /> </Route> </Router> ), document.getElementById('example'))
Loginコンポーネントの中で認証させたいのでこんなかんじにしてみる。
さて認証画面が表示されるでしょうか?!
class Login extends React.Component { showLock: function() { this.props.lock.show(); } render: function() { return ( <div> <button onClick={this.showLock}>Login</button> </div>); } }
これだけで、認証画面が表示されます。
でも、認証成功後にエラーとなってしまった。
Auth0のログ(左メニューのLogsを押す)を読んでみると
Description: Callback URL mismatch. http://localhost:8080/login is not in the list of authorized callback URLs: http://localhost:8080/callback
どうもAuth0の管理画面に設定したコールバックの設定「http://localhost:8080/callback」がだめ
と言っているようです。
SPAなのでコールバックってなんだろうという感じもしますが。
Auth0が呼んでくれるのかな?
でもAuth0側からlocalhostを呼ぶっていうのも、なんか変な気もするとか考えたり。
紋々としていましたが・・
開発環境ではhttp://localhost:8080/loginで認証画面が表示するように
しています。では、「http://localhost:8080/login」
をAuth0の設定画面のcallback urlに設定してみようではないか。
うまくできたけれども・・・
認証が済むと、コールバックでこんなかんじで帰ってくるようになった。http://localhost:8080/login#access_token=foo,user_token=bar
そうするとReact.jsでパスを処理したいのですが・・
処理されずブラウザはHTTPアクセスにいってしまうのです。
login#ホニャララをLoginコンポーネントで処理したいのに。
React.render(( <Router history={history} createElement={createElement}> <Route path="/" component={App}> <Route path="/home" component={Home} > <Route path="/stamp/:stamp" components={{ content: Stamp, sidebar: StampSidebar }}> <Route path=":image" component={StampCanvas} /> </Route> </Route> <Route path="/login" component={Login} /> <Route path="/logout" component={Logout} /> <Route path="/new" component={New} /> </Route> </Router> ), document.getElementById('example'))
こんな風に変えてみたけど、ダメだぁ。
Not working!!
React.render(( <Router history={history} createElement={createElement}> <Route path="/" component={App}> <Route path="/home" component={Home} > <Route path="/stamp/:stamp" components={{ content: Stamp, sidebar: StampSidebar }}> <Route path=":image" component={StampCanvas} /> </Route> </Route> <Route path="/login(#**)" component={Login} /> <Route path="/logout" component={Logout} /> <Route path="/new" component={New} /> </Route> </Router> ), document.getElementById('example'))
あららら。わからない。
React-Router経由にするとcallback(Redirect)でブラウザがHTTPアクセス
してしまう。どうして、単体Reactでは動作するのだろう?
ここまできてやっと気づいた
認証後にリダイレクトが起きて動くようにしておかなくてはいけないということ。/loginには実際にはコンテンツがないわけで
historyAPIでpushstateして履歴を積み上げているだけで
/loginへのページの実体は存在していないから。
ルートから認証させる必要あり
/loginで認証させるのではなくて/から認証させる必要あり。
メニューで認証させるのをやめよう。