colymba / silverstripe-restfulapi

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

API Access denied on Member model #55

Open Kingy opened 9 years ago

Kingy commented 9 years ago

I'm trying to access the Member model in the API but am just getting API access denied. All other models are working perfectly fine. See config below:

Member:
  api_access: true
Subscriber:
  api_access: true
Subscription:
  api_access: true
Product:
  api_access: true
RESTfulAPI:
  authentication_policy: true
  access_control_policy: 'ACL_CHECK_CONFIG_ONLY'
  dependencies:
    authenticator: '%$RESTfulAPI_TokenAuthenticator'
  cors:
    Enabled: true
    Allow-Origin: '*'
    Allow-Headers: '*'
    Allow-Methods: 'OPTIONS, GET, POST, PUT'
    Max-Age: 86400
  RESTfulAPI_TokenAuthenticator:
    tokenOwnerClass: 'Member'
    autoRefreshLifetime: true
Member:
  extensions:
    - RESTfulAPI_TokenAuthExtension
colymba commented 9 years ago

First thing I can think of is that the Member you use to access the API doesn't the right to read the Member record you are trying to access, maybe? Since Member has it's default set of canView etc...

You don't have any other extension on the Member object?

Kingy commented 9 years ago

The user I'm using is an admin so I don't think it's that.

I do have an extension. Do I need to add that instead of Member?

colymba commented 9 years ago

For the extension I was just wondering if there might be code there that affects it... maybe? can you post the code?

MarkyParkyJozi commented 8 years ago

Im having a similar issue, I can't really see any support which makes me think the answers easy and im just confused. I would like to be able to create a new member by posting to a url: "http://mysite.local/api/Member" with data like : {"FirstName":"test1"}.

When I try the above I get a "Token invalid" response. Heres my config.yml

---
Name: restfulapi
After: 'framework/*','cms/*'
---
# ---------------------------------
# Routing
Director:
  rules:
    'api': 'RESTfulAPI'
ArkOrder:
  api_access: 'true'
Ark:
  api_access: 'true'
#DONT NEED TO POST TO BADGE REMOVE FOR PRODUCTION
Badge:
  api_access: 'true'

# RestfulAPI config
RESTfulAPI:
  authentication_policy: true
  access_control_policy: 'ACL_CHECK_CONFIG_ONLY'
  dependencies:
    authenticator: '%$RESTfulAPI_TokenAuthenticator'
  cors:
    Enabled: true
    Allow-Origin: '*'
    Allow-Headers: '*'
    Allow-Methods: 'OPTIONS, GET, POST, PUT'
    Max-Age: 86400
  RESTfulAPI_TokenAuthenticator:
    tokenOwnerClass: 'Member'
Member:
  extensions:
      - RESTfulAPI_TokenAuthExtension
colymba commented 8 years ago

The "Token invalid" error is because you are using an authenticator component: RESTfulAPI_TokenAuthenticator which restricts access to the api to only authorized requests.

This means you need to pass a X-Silverstripe-Apitoken in the header of your request. Here is the doc: https://github.com/colymba/silverstripe-restfulapi/blob/master/doc/TokenAuthenticator.md.

The token itself comes from the DataObject who has the RESTfulAPI_TokenAuthExtension extension, in your case, Member. The token can be generated via the login method for example api/auth/login?email=XXX&pwd=XXX (https://github.com/colymba/silverstripe-restfulapi/blob/master/code/authenticator/RESTfulAPI_TokenAuthenticator.php#L132)

Or you could just disable it for test purposes by setting authentication_policy: false on the RESTfulAPI config.

MarkyParkyJozi commented 8 years ago

I apologize I was a bit vague.

Its for registration. So for a new user to create a profile in order to login. At this point in the journey he (the user) would not have a token but would require one only after registering

colymba commented 8 years ago

@MarkyParkyJozi I see... authentication_policy can take an array of HTTP methods, so you could leave out POST ($authentication_policy = array('GET', 'PUT', 'DELETE');) so anyone can create new Members... theoretically, it should work....?

MarkyParkyJozi commented 8 years ago

THANKS @colymba it works if I place it in my yml as:

RESTfulAPI:
  authentication_policy: 'GET,DELETE,PUT'

But thats a bit dangerous so i tried extending my member so that only the 'Member' model would have the policy:

class MyMemberExtension extends DataExtension {
    /**

     * Modify the field set to be displayed in the CMS detail pop-up
     */
    private static $has_many = array(
        'Arks' => 'Ark'
    );

    public function canCreate($member = null) {
        //return Permission::check('CMS_ACCESS_CMSMain', 'any', $member);
        return true;
    }

    // define additional properties
    private static $has_one = array();
    private static $authentication_policy = array('GET', 'PUT', 'DELETE');
    private static $belongs_many_many = array();

}

and my config.yml:

Director:
  rules:
    'api': 'RESTfulAPI'
ArkOrder:
  api_access: 'GET,POST,PUT'
Ark:
  api_access: 'GET,POST,PUT'
#DONT NEED TO POST TO BADGE REMOVE FOR PRODUCTION
Badge:
  api_access: 'GET,PUT,POST'

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

  RESTfulAPI_TokenAuthenticator:
    tokenOwnerClass: 'MyMemberExtension'
MyMemberExtension:
    extensions:
      - RESTfulAPI_TokenAuthExtension

Member:
  api_access: 'GET,POST,PUT'
  extensions:
    - MyMemberExtension

And then my post would now be to : http://mysite.local/api/MyMemberExtension but its the same 'Token invalid' message

Im still pretty new to silverstripe so maybe Im missing some fundamentals? Surely this pattern or something similar has been done before

colymba commented 8 years ago

@MarkyParkyJozi authentication_policy just wont be checked on your dataExtension and also, /api/MyMemberExtension isn't right, you can't call DataExtensions like that, they are added to DataObjects...

MarkyParkyJozi commented 8 years ago

Brilliant!, knowing what wont work is half the battle. @colymba can you direct me to any documentation that would allow me to use the RESTfulAPI and have the desired pattern of allowing registration

colymba commented 8 years ago

@MarkyParkyJozi this is now going off topic for this issue.... bets thing is for you to create a new issue and we can continue there....