colymba / silverstripe-restfulapi

SilverStripe RESTful API with a default JSON serializer.
BSD 3-Clause "New" or "Revised" License
64 stars 34 forks source link

Access token authenticated Member::currentUser() in onAfterDeserialize function #72

Closed jonshutt closed 7 years ago

jonshutt commented 7 years ago

I'm wondering it's possible to access Member::currentUser() data within the onAfterDeserialize function on my model.

I'm logging in and authenticating ok using the API and passing the token back which I can read in the canCreate() function.

Idea is that if a user creates an entry, it will put their ID against it in the onAfterDeserialize rather than posting up their ID

colymba commented 7 years ago

If you are using the TokenAuth and the token is stored on a Member dataobject, when the Authenticator validates the token the Member gets login at the same time.

So theoretically, Member::currentUser() should work anywhere. Have you tried it?

jonshutt commented 7 years ago

I think my problem my be that the member is authenticated when I log in and get their details, but i haven't set up the 'log' dataobject / endpoint to use the authenticated user...

Log:
  api_access: 'GET,POST'

Member:
  api_access: 'GET'
  extensions:
    - RESTfulAPI_TokenAuthExtension
colymba commented 7 years ago

That config snippet seems fine. What's the config for RestfulAPI?

jonshutt commented 7 years ago

config is

Log:
  api_access: 'GET,POST'

Member:
  extensions:
    - RESTfulAPI_TokenAuthExtension

# RestfulAPI config
RESTfulAPI:
  #authentication_policy: true
  access_control_policy: 'ACL_CHECK_CONFIG_AND_MODEL'
  dependencies:
    authenticator: '%$RESTfulAPI_TokenAuthenticator'
  cors:
    Enabled: true
    Allow-Origin: '*'
    Allow-Headers: '*'
    Allow-Methods: 'GET,POST'
    Max-Age: 86400
  RESTfulAPI_TokenAuthenticator:
    tokenOwnerClass: 'Member'

in my 'log' data object I have

public function onAfterDeserialize(&$data) { print_r($data); print_r(Member::currentUser()); print_r(Member::currentUser()->ID); } which is displaying the data posted, but not the member info.

if i add a 'canCreate' function eg:

function canCreate($member = null) { if(!$member) $member = Member::currentUser(); print "create:"; print $member->ID; return true; }

then within there I can see the member info in there

colymba commented 7 years ago

You need to uncomment authentication_policy: true (you can change true to an array of HTTP method if for example you only want to authenticate request that change data...). Adding the RESTfulAPI_TokenAuthExtension is not enough.

Am pretty sure you get a Member ID in the canCreate method because SilverStripe has its own Member retrieval mechanism if non is passed as argument.

jonshutt commented 7 years ago

Hi there,

Many thanks - I think there's a combination of lots of things going on here - I'm getting close now. One issue I seem to have is that $HTTP requests from AngularJS aren't sending the token in the required format - using POSTMAN is now working, so with that working it isolate the final issue.

Really appreciate your help, and once it's working and I get some free time I'll post my solution for other people reference.,

colymba commented 7 years ago

by default the token has to be passed in an HTTP header X-Silverstripe-Apitoken See https://github.com/colymba/silverstripe-restfulapi/blob/master/doc/TokenAuthenticator.md#restfulapi_tokenauthenticator

Or fall back to a query variable ?token

jonshutt commented 7 years ago

I seem to have it all working now. Cheers.

colymba commented 7 years ago

Awesome!