Knock JWT Auth for Rails API + Create React App

Nick Hartunian
Jul 10, 2017 · 7 min read

class User < ApplicationRecord
has_secure_password
end
admin = User.new
admin.email = 'admin@bananas.com'
admin.password = 'bananaKing'
admin.password_confirmation = 'bananaKing'
admin.admin = true
admin.save
user = User.new
user.email = 'user@bananas.com'
user.password = 'bananaBro'
user.password_confirmation = 'bananaBro'
user.save
Rails.application.routes.draw do
scope '/api' do
resources :bananas
post 'user_token' => 'user_token#create'
end
end
class ApplicationController < ActionController::API
include Knock::Authenticable
end
class BananasController < ApplicationController
before_action :authenticate_user
before_action :set_banana, only: [:show, :update, :destroy]

render() {
return (
<div className="App">
<h1 style={{marginTop: "20vh", marginBottom: "5vh"}}>
Banana Management System
</h1>
<form>
<label htmlFor="email">Email: </label>
<br />
<input
name="email"
id="email"
type="email"
/>
<br /><br />
<label htmlFor="password">Password:</label>
<br />
<input
name="password"
id="password"
type="password"
/>
</form>
<br />
<button
onClick={this.login}
>
Login
</button>
<br />
<button
onClick={this.getBananas}
style={{marginTop: "10vh"}}
>
Get Bananas
</button>
<p>{this.state.bananasReceived}</p>
</div>
);
}
login () {
const email = $("#email").val()
const password = $("#password").val()
const request = {"auth": {"email": email, "password": password}}
console.log(request)
$.ajax({
url: "http://localhost:3000/api/user_token",
type: "POST",
data: request,
dataType: "json",
success: function (result) {
console.log(result)
localStorage.setItem("jwt", result.jwt)
}
})
}
getBananas() {
let token = "Bearer " + localStorage.getItem("jwt")
console.log(token)
$.ajax({
url: "http://localhost:3000/api/bananas",
type: "GET",
beforeSend: function(xhr){xhr.setRequestHeader('Authorization', token)},
context: this, // Allows us to use this.setState inside success
success: function (result) {
console.log(result)
this.setState({bananasReceived: JSON.stringify(result)})
}
})
}
def index
if current_user.admin?
@bananas = Banana.all
render json: @bananas
end
end
import React, { Component } from 'react'
import './App.css'
// $ is a shortcut for jQuery methods
import $ from 'jquery'
class App extends Component {
constructor(props) {
super(props)
this.state = {bananasReceived: ""}
this.getBananas = this.getBananas.bind(this)
}
login () {
const email = $("#email").val()
const password = $("#password").val()
const request = {"auth": {"email": email, "password": password}}
console.log(request)
$.ajax({
url: "http://localhost:3000/api/user_token",
type: "POST",
data: request,
dataType: "json",
success: function (result) {
console.log(result)
localStorage.setItem("jwt", result.jwt)
}
})
}
getBananas(admin) {
let token = "Bearer " + localStorage.getItem("jwt")
let url = ""
url = admin ? "http://localhost:3000/api/bananas" : "http://localhost:3000/api/bananas/1"
console.log(token)
$.ajax({
url: url,
type: "GET",
beforeSend: function(xhr){xhr.setRequestHeader('Authorization', token)},
context: this, // Allows us to use this.setState inside success
success: function (result) {
console.log(result)
this.setState({bananasReceived: JSON.stringify(result)})
}
})
}
render() {
return (
<div className="App">
<h1 style={{marginTop: "20vh", marginBottom: "5vh"}}>
Banana Management System
</h1>
<form>
<label htmlFor="email">Email: </label>
<br />
<input
name="email"
id="email"
type="email"
/>
<br /><br />
<label htmlFor="password">Password:</label>
<br />
<input
name="password"
id="password"
type="password"
/>
</form>
<br />
<button
onClick={this.login}
>
Login
</button>
<br />
<button
onClick={() => { this.getBananas(false) }}
style={{marginTop: "10vh"}}
>
Get One Banana
</button>
<br />
<button
onClick={() => { this.getBananas(true) }}
style={{marginTop: "2vh"}}
>
Get Bananas
</button>
<p>{this.state.bananasReceived}</p>
</div>
);
}
}
export default App

Nick Hartunian

Written by

Currently an intern in the Silicon Valley. Enjoys Model UN.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade