Slide 1

Slide 1 text

How to make a full fledged REST API with Django OAuth Toolkit

Slide 2

Slide 2 text

why?

Slide 3

Slide 3 text

introducing the marvelous TIMETRACKER

Slide 4

Slide 4 text

At first... one tool single project deployed once and everything was fine...

Slide 5

Slide 5 text

The times they are a-changin'

Slide 6

Slide 6 text

Frontend applications Multiple Devices to Support

Slide 7

Slide 7 text

A lot of projects timetracker-backend timetracker-web timetracker-android timetracker-ios timetracker-desktop (linux, win, osx) moreover...

Slide 8

Slide 8 text

Third party services wants to connect with your application!

Slide 9

Slide 9 text

What's in the backend? A service that expose an amazing and reliable REST API

Slide 10

Slide 10 text

Backend Recipe Django Django REST Framework Django OAuth Toolkit

Slide 11

Slide 11 text

Models c l a s s A c t i v i t y ( m o d e l s . M o d e l ) : n a m e = m o d e l s . C h a r F i e l d ( m a x _ l e n g t h = 1 0 0 ) d e s c r i p t i o n = m o d e l s . T e x t F i e l d ( b l a n k = T r u e ) c l a s s T i m e E n t r y ( m o d e l s . M o d e l ) : a c t i v i t y = m o d e l s . F o r e i g n K e y ( A c t i v i t y ) u s e r = m o d e l s . F o r e i g n K e y ( s e t t i n g s . A U T H _ U S E R _ M O D E L ) d e s c r i p t i o n = m o d e l s . T e x t F i e l d ( b l a n k = T r u e ) s t a r t = m o d e l s . D a t e T i m e F i e l d ( b l a n k = T r u e , n u l l = T r u e ) e n d = m o d e l s . D a t e T i m e F i e l d ( b l a n k = T r u e , n u l l = T r u e )

Slide 12

Slide 12 text

API Endpoints Url Methods Semantic /api/activities/ GET, POST list, create /api/activities// GET, PUT/PATCH, DELETE detail, update, remove /api/tracks/ GET, POST list, create /api/tracks// GET, PUT/PATCH, DELETE detail, update, remove

Slide 13

Slide 13 text

Deep into DRF in 5 minutes

Slide 14

Slide 14 text

Serialize Data c l a s s A c t i v i t y S e r i a l i z e r ( s e r i a l i z e r s . S e r i a l i z e r ) : p k = s e r i a l i z e r s . F i e l d ( ) n a m e = s e r i a l i z e r s . C h a r F i e l d ( m a x _ l e n g t h = 1 0 0 ) d e s c r i p t i o n = s e r i a l i z e r s . C h a r F i e l d ( r e q u i r e d = F a l s e ) d e f r e s t o r e _ o b j e c t ( s e l f , a t t r s , i n s t a n c e = N o n e ) : i f i n s t a n c e : # U p d a t e e x i s t i n g i n s t a n c e i n s t a n c e . n a m e = a t t r s . g e t ( ' n a m e ' , i n s t a n c e . n a m e ) i n s t a n c e . d e s c r i p t i o n = a t t r s . g e t ( ' d e s c r i p t i o n ' , i n s t a n c e . d e s c r i p t i o n ) r e t u r n i n s t a n c e # C r e a t e n e w i n s t a n c e r e t u r n A c t i v i t y ( * * a t t r s ) > > > s e r i a l i z e r = A c t i v i t y S e r i a l i z e r ( a c t i v i t y ) > > > s e r i a l i z e r . d a t a # { ' p k ' : 1 , ' n a m e ' : u ' T i m e t r a c k e r ' , ' d e s c r i p t i o n ' : u ' W o r k i n o n t i m e t r a c k e r ' }

Slide 15

Slide 15 text

Simplify! Model Serializer c l a s s A c t i v i t y S e r i a l i z e r ( s e r i a l i z e r s . M o d e l S e r i a l i z e r ) : c l a s s M e t a : m o d e l = A c t i v i t y

Slide 16

Slide 16 text

API Endpoint Views What do we need? respect REST semantic user authentication permissions checks (also object level permission) pagination response and request formatting it's a lot of stuff!

Slide 17

Slide 17 text

Keep Calm and use DRF!

Slide 18

Slide 18 text

Settings R E S T _ F R A M E W O R K = { ' D E F A U L T _ A U T H E N T I C A T I O N _ C L A S S E S ' : ( ' r e s t _ f r a m e w o r k . a u t h e n t i c a t i o n . S e s s i o n A u t h e n t i c a t i o n ' , ) , ' D E F A U L T _ P E R M I S S I O N _ C L A S S E S ' : ( ' r e s t _ f r a m e w o r k . p e r m i s s i o n s . I s A u t h e n t i c a t e d ' , ) , ' D E F A U L T _ R E N D E R E R _ C L A S S E S ' : ( ' r e s t _ f r a m e w o r k . r e n d e r e r s . J S O N R e n d e r e r ' , ) , ' D E F A U L T _ P A R S E R _ C L A S S E S ' : ( ' r e s t _ f r a m e w o r k . p a r s e r s . J S O N P a r s e r ' , ) }

Slide 19

Slide 19 text

Api View c l a s s A c t i v i t y L i s t ( A P I V i e w ) : " " " L i s t a l l a c t i v i t i e s , o r c r e a t e a n e w a c t i v i t y . " " " d e f g e t ( s e l f , r e q u e s t , f o r m a t = N o n e ) : a c t i v i t i e s = A c t i v i t y . o b j e c t s . a l l ( ) s e r i a l i z e r = A c t i v i t y S e r i a l i z e r ( a c t i v i t i e s , m a n y = T r u e ) r e t u r n R e s p o n s e ( s e r i a l i z e r . d a t a ) d e f p o s t ( s e l f , r e q u e s t , f o r m a t = N o n e ) : s e r i a l i z e r = A c t i v i t y S e r i a l i z e r ( d a t a = r e q u e s t . D A T A ) i f s e r i a l i z e r . i s _ v a l i d ( ) : s e r i a l i z e r . s a v e ( ) r e t u r n R e s p o n s e ( s e r i a l i z e r . d a t a , s t a t u s = s t a t u s . H T T P _ 2 0 1 _ C R E A T E D ) r e t u r n R e s p o n s e ( s e r i a l i z e r . e r r o r s , s t a t u s = s t a t u s . H T T P _ 4 0 0 _ B A D _ R E Q U E S T ) u r l p a t t e r n s = p a t t e r n s ( ' ' , u r l ( r ' ^ a p i / a c t i v i t i e s / $ ' , A c t i v i t y L i s t . a s _ v i e w ( ) ) , # . . . )

Slide 20

Slide 20 text

Simplify! Generic Class Based Views c l a s s A c t i v i t y L i s t ( g e n e r i c s . L i s t C r e a t e A P I V i e w ) : q u e r y s e t = A c t i v i t y . o b j e c t s . a l l ( ) s e r i a l i z e r _ c l a s s = A c t i v i t y S e r i a l i z e r c l a s s A c t i v i t y D e t a i l ( g e n e r i c s . R e t r i e v e U p d a t e D e s t r o y A P I V i e w ) : q u e r y s e t = A c t i v i t y . o b j e c t s . a l l ( ) s e r i a l i z e r _ c l a s s = A c t i v i t y S e r i a l i z e r c l a s s T i m e E n t r y L i s t ( g e n e r i c s . L i s t C r e a t e A P I V i e w ) : q u e r y s e t = T i m e E n t r y . o b j e c t s . a l l ( ) s e r i a l i z e r _ c l a s s = T i m e E n t r y S e r i a l i z e r c l a s s T i m e E n t r y D e t a i l ( g e n e r i c s . R e t r i e v e U p d a t e D e s t r o y A P I V i e w ) : q u e r y s e t = T i m e E n t r y . o b j e c t s . a l l ( ) s e r i a l i z e r _ c l a s s = T i m e E n t r y S e r i a l i z e r

Slide 21

Slide 21 text

BONUS! builtin browsable api

Slide 22

Slide 22 text

How to authorize client applications? Third party app wants to access your user's data

Slide 23

Slide 23 text

Problems Store the user password in the app The app has a full access to user account User has to change his password to revoke the access Compromised apps expose the user password Reference: http://www.slideshare.net/aaronpk/an-introduction-to-oauth2

Slide 24

Slide 24 text

The OAuth2 Authorization Framework How does it work?

Slide 25

Slide 25 text

Use Case

Slide 26

Slide 26 text

Actors Resource Owner: The User Resource Server: Timetracker API Authorization Server: The same as the Resource Server Client: Songify App

Slide 27

Slide 27 text

The Authorization Code Flow

Slide 28

Slide 28 text

Step 1 Client registers with the Authorization Server The Authorization Server provides client id and client secret

Slide 29

Slide 29 text

Step 2 Client directs the Resource Owner to an authorization server via its user- agent

Slide 30

Slide 30 text

Step 3 The Authorization Server authenticates the Resource Owner and obtains authorization

Slide 31

Slide 31 text

Step 4 The Authorization Server directs the Resource Owner back to the client with the authorization code

Slide 32

Slide 32 text

Step 5 The Client exchange the authorization code for a token The token is used by the Client to authenticate requests

Slide 33

Slide 33 text

Django OAuth Toolkit Django 1.4, 1.5, 1.6, 1.7 Python2 & Python3 Built on top of oauthlib https://github.com/evonove/django-oauth-toolkit

Slide 34

Slide 34 text

DOT and Django I N S T A L L E D _ A P P S + = ( ' o a u t h 2 _ p r o v i d e r ' , ) u r l p a t t e r n s + = p a t t e r n s ( ' ' , u r l ( r ' ^ o / ' , i n c l u d e ( ' o a u t h 2 _ p r o v i d e r . u r l s ' , n a m e s p a c e = ' o a u t h 2 _ p r o v i d e r ' ) ) , ) Create a protected endpoint f r o m o a u t h 2 _ p r o v i d e r . v i e w s . g e n e r i c i m p o r t P r o t e c t e d R e s o u r c e V i e w c l a s s A p i E n d p o i n t ( P r o t e c t e d R e s o u r c e V i e w ) : d e f g e t ( s e l f , r e q u e s t , * a r g s , * * k w a r g s ) : r e t u r n H t t p R e s p o n s e ( ' P r o t e c t e d w i t h O A u t h 2 ! ' )

Slide 35

Slide 35 text

Batteries Included Builtin views to register developer apps Form view for user authorization

Slide 36

Slide 36 text

Integrates with DRF R E S T _ F R A M E W O R K = { ' D E F A U L T _ A U T H E N T I C A T I O N _ C L A S S E S ' : ( ' o a u t h 2 _ p r o v i d e r . e x t . r e s t _ f r a m e w o r k . O A u t h 2 A u t h e n t i c a t i o n ' , ) }

Slide 37

Slide 37 text

Exchange the code Unauthenticated access Authenticated access LET'S TEST IT! Authorization endpoint h t t p : / / l o c a l h o s t : 8 0 0 0 / o / a u t h o r i z e ? r e s p o n s e _ t y p e = c o d e & c l i e n t _ i d = < c l i e n t _ i d > & r e d i r e c t _ u r i = h t t p : / / e x a m p l e . c o m c u r l - X P O S T - d " g r a n t _ t y p e = a u t h o r i z a t i o n _ c o d e & c o d e = < c o d e > & r e d i r e c t _ u r i = h t t p : / / e x a m p l e . c o m / " h t t p : / / < c l i e n c u r l h t t p : / / l o c a l h o s t : 8 0 0 0 / a p i / a c t i v i t i e s / c u r l - H " A u t h o r i z a t i o n : B e a r e r < y o u r _ a c c e s s _ t o k e n > " h t t p : / / l o c a l h o s t : 8 0 0 0 / a p i / a c t i v i t i e s / < / y o u r _ a c c e s s _ t o

Slide 38

Slide 38 text

Future plans OAuth1 support OpenID connector NoSQL storages support help needed

Slide 39

Slide 39 text

Thank you!  @synasius https://evonove.it