Secured resource access
Resource calls made with the Onegini SDK are always secured with certificate pinning. Payload encryption can be enabled in the Token Server. Debug detection can be configured in the Config Model, if enabled the SDK will verify there is no debugger attached to the app process before fetching the resource. SDK does not perform any mapping or conversion of the response payload. It is up to the App how to process a valid response from the back-end.
Get resource flow:
1. APP -> SDK: Instruct the SDK to request a resource.
2. SDK -> Resource Gateway: Request a resource at the resource gateway by sending the access token in the request.
3. Resource Gateway -> Token Server: Validate the provided token.
4. Token Server --> Resource Gateway: Details regarding the access token like scope and user, which will be verified by the resource gateway.
5. Resource Gateway -> Resource Server: Get the resource.
6. Resource Server --> Resource Gateway: Return the resource.
7. Resource Gateway --> SDK: Return the resource.
8. SDK --> APP: Resource is returned to the APP which has knowledge of the context of the returned resource.
The SDK can fetch a secure resource in three distinct ways. For a resource that is tied to a user (e.g. account information or transactions), the SDK can execute an authenticated request. For a resource that is tied to an application but are not unique per user, for example application assets, the SDK can execute an anonymous request. For a resource that can be fetched without any additional authentication, but for which you would still like to use certificate pinning and jailbreak/debug detection the SDK can execute an unauthenticated request.
Authenticated requests
Secure resource access is performed using ONGUserClient
for authorized calls and ONGDeviceClient
for anonymous calls.
Instances can be obtained by using @property (nonatomic, readonly) ONGUserClient *userClient;
and @property (nonatomic, readonly) ONGDeviceClient *deviceClient;
respectively, or by calling [ONGUserClient sharedInstance]and [ONGDeviceClient sharedInstance]
respectively. Attempt to obtain clients instances without configuring the SDK first, will result in throwing NSInternalInconsistencyException
exception.
Performing a resource call
For user specific resources the user needs to be authenticated and a token that is connected to the authenticated user is presented to the back-end when fetching a resource.
The SDK requires that the user is authenticated. Fetching user specific resources using the Onegini SDK is done through the following ONGUserClient
method:
- (nullable ONGNetworkTask *)fetchResource:(ONGResourceRequest *)request completion:(nullable void (^)(ONGResourceResponse * _Nullable response, NSError * _Nullable error))completion;
Example of an authenticated resource call
Objective-C
ONGResourceRequest *request = [[ONGResourceRequest alloc] initWithPath:@"/api/users" method:@"GET"];
[[ONGUserClient sharedInstance] fetchResource:request completion:^(ONGResourceResponse * _Nullable response, NSError * _Nullable error) {
// handle response
}];
Swift
let request = ONGResourceRequest(path:"/api/users/" method:"GET")
ONGUserClient.sharedInstance().fetchResource(request) { response, error in
// handle response
}
Implicit requests
Implicit resource requests are performed using the ONGUserClient
. It can be obtained by using the
@property (nonatomic, readonly) ONGUserClient *userClient;
of the ONGClient
object or by calling the +[ONGUserClient sharedInstance]
method.
Performing a resource call
Implicit resource calls are authenticated using an implicit access token. It is obtained by the SDK during implicit user authentication. You can find more information about the process in the Implicit authentication guide. Fetching implicit resources using the Onegini SDK is done through the following ONGUserClient method:
- (nullable ONGNetworkTask *)fetchImplicitResource:(ONGResourceRequest *)request completion:(nullable void (^)(ONGResourceResponse *_Nullable response, NSError *_Nullable error))completion;
Example of an implicit resource call
Objective-C
ONGResourceRequest *request = [[ONGResourceRequest alloc] initWithPath:@"/api/users" method:@"GET"];
[[ONGUserClient sharedInstance] fetchImplicitResource:request completion:^(ONGResourceResponse * _Nullable response, NSError * _Nullable error) {
// handle response
}];
Swift
let request = ONGResourceRequest(path:"/api/users/" method:"GET")
ONGUserClient.sharedInstance().fetchImplicitResource(request) { response, error in
// handle response
}
Anonymous requests
Secure anonymous resource access is performed using the ONGDeviceClient
. It can be obtained by using the
@property (nonatomic, readonly) ONGDeviceClient *deviceClient;
of the ONGClient
object or by calling the +[ONGDeviceClient sharedInstance]
method. Any
attempt to obtain the ONGDeviceClient
without configuring the SDK first, will result in throwing a NSInternalInconsistencyException
exception.
Performing a resource call
For anonymous resources a token that is connected to this device is presented to the back-end. Anonymous resource calls allow you to fetch data that is not user specific but should not be publicly available to anybody knowing the API.
The SDK requires the device (application) to be registered, valid and authenticated. Fetching anonymous resources using the Onegini SDK is done through the
following ONGDeviceClient
method:
- (nullable ONGNetworkTask *)fetchResource:(ONGResourceRequest *)request completion:(nullable void (^)(ONGResourceResponse * _Nullable response, NSError * _Nullable error))completion;
Example of an anonymous resource call
Objective-C
ONGResourceRequest *request = [[ONGResourceRequest alloc] initWithPath:@"/api/users" method:@"GET"];
[[ONGDeviceClient sharedInstance] fetchResource:request completion:^(ONGResourceResponse * _Nullable response, NSError * _Nullable error) {
// handle response
}];
Swift
let request = ONGResourceRequest(path:"/api/users/" method:"GET")
ONGDeviceClient.sharedInstance().fetchResource(request) { response, error in
// handle response
}
Unauthenticated requests
Securing unauthenticated requests is performed using the ONGDeviceClient
. It can be obtained by using the
@property (nonatomic, readonly) ONGDeviceClient *deviceClient;
of the ONGClient
object or by calling the +[ONGDeviceClient sharedInstance]
method.
attempt to obtain the ONGDeviceClient
without configuring the SDK first, will result in throwing a NSInternalInconsistencyException
exception.
Performing a resource call
For unauthenticated requests no token is presented to the back end. Only certificate pinning and jailebreak/debug detection are
used when fetching unauthenticated resources. Fetching unauthenticated resources using the Onegini SDK is done through the
following ONGDeviceClient
method:
- (nullable ONGNetworkTask *)fetchUnauthenticatedResource:(ONGResourceRequest *)request completion:(nullable void (^)(ONGResourceResponse * _Nullable response, NSError * _Nullable error))completion;
Example of an unauthenticated resource call
Objective-C
ONGResourceRequest *request = [[ONGResourceRequest alloc] initWithPath:@"/api/users" method:@"GET"];
[[ONGDeviceClient sharedInstance] fetchUnauthenticatedResource:request completion:^(ONGResourceResponse * _Nullable response, NSError * _Nullable error) {
// handle response
}];
Swift
let request = ONGResourceRequest(path:"/api/users/" method:"GET")
ONGDeviceClient.sharedInstance().fetchUnauthenticatedResource(request) { response, error in
// handle response
}
Request Construction
Manual
Both authenticated and anonymous resource calls starts from the ONGResourceRequest
construction. The request object combines the following properties:
path
- URI path, appended toONGResourceBaseURL
set within theONGClient
configuration.method
- HTTP request method, can be one of@"GET"
,@"POST"
,@"PUT"
and@"DELETE"
.parameters
- a dictionary of parameters used for the request. Parameters are appended to the URL or provided within a body depending on the request method (respectively@"GET"
or@"POST"
).parametersEncoding
- the encoding used for params, possible values areONGParametersEncodingJSON
orONGParametersEncodingFormURL
(seeONGResourceRequest.h
for the declarations). The default value isONGParametersEncodingJSON
.body
- a raw bady of the request. If specified it overwrites theparameters
andparametersEncoding
.multipartData
- the object that represents the multipart data that should be sent. Themultipart/form-data
Content-Type header is added automatically. Only the HTTP POST method is supported for a multipart request. Note that if you add multipart data theparametersEncoding
property is neglected.headers
- additional headers added to the HTTP request. The Onegini SDK takes the responsibility of managing theAuthorization
andUser-Agent
headers. These cannot be modified / provided.
In order to create an instance of the ONGResourceRequest
you may use one of the built-in initializers:
- (instancetype)initWithPath:(NSString *)path method:(NSString *)method;
- (instancetype)initWithPath:(NSString *)path method:(NSString *)method parameters:(nullable NSDictionary<NSString *, id> *)parameters;
- (instancetype)initWithPath:(NSString *)path method:(NSString *)method parameters:(nullable NSDictionary<NSString *, id> *)parameters encoding:(ONGParametersEncoding)encoding;
- (instancetype)initWithPath:(NSString *)path method:(NSString *)method parameters:(nullable NSDictionary<NSString *, id> *)parameters encoding:(ONGParametersEncoding)encoding headers:(nullable NSDictionary<NSString *, NSString *> *)headers;
- (instancetype)initWithPath:(NSString *)path method:(NSString *)method body:(nullable NSData *)body headers:(nullable NSDictionary<NSString *, NSString *> *)headers;
- (instancetype)initWithPath:(NSString *)path method:(NSString *)method parameters:(nullable NSDictionary<NSString *, id> *)parameters multipartData:(NSArray<ONGMultipartData *> *)multipartData;
In addition to ONGResourceRequest
, which is immutable by design there is a counterpart - ONGMutableResourceRequest
that allows you to modify all of the available properties one by one.
Both ONGResourceRequest
and ONGMutableResourceRequest
conform to the NSCopying
and NSMutableCopying
protocols for easier usage.
Example of request construction
Objective-C
ONGResourceRequest *request = [[ONGResourceRequest alloc] initWithPath:@"/api/users/" method:@"GET" parameters:@{@"username": @"[email protected]"}];
// mutable version
ONGMutableRequest *request = [[ONGMutableRequest alloc] initWithPath:@"/api/users/" method:@"GET"];
request.headers = @{@"X-Flags": @"1000010"};
request.parameters = @{@"username": @"[email protected]"};
request.parametersEncoding = ONGParametersEncodingJSON;
Swift
let request = ONGResourceRequest(path:"/api/users/" method:"GET" parameters:{"username": "[email protected]"})
// mutable version
let request = ONGMutableRequest(path:@"/api/users/" method:"GET")
request.headers = {"X-Flags": "1000010"}
request.parameters = {"username": "[email protected]"}
request.parametersEncoding = .JSON
Request Builder
In order to simplify request construction the SDK offers a ONGRequestBuilder
class, that allow you to build new immutable requests through a set of methods
that reflect ONGResourceRequest
properties and build an actual request instance by calling the -[ONGRequestBuilder build]
method:
@interface ONGRequestBuilder : NSObject
- (instancetype)setMethod:(NSString *)method;
- (instancetype)setPath:(NSString *)path;
- (instancetype)setParameters:(NSDictionary<NSString *, id> *)parameters;
- (instancetype)setParametersEncoding:(ONGParametersEncoding)parametersEncoding;
- (instancetype)setBody:(NSData *)body;
- (instancetype)setMultipartData:(NSArray<ONGMultipartData *> *)multipartData;
- (instancetype)setHeaders:(NSDictionary<NSString *, NSString *> *)headers;
- (ONGResourceRequest *)build;
@end
Example request construction using the builder
Objective-C
ONGResourceRequest *request = [[[[ONGRequestBuilder builder] setMethod:@"GET"] setPath:@"/api/users"] build];
Swift
let request = ONGRequestBuilder().setMethod("GET").setPath("/api/users").setParameters({"username": "[email protected]"}).build()
Handling the resource response
The responsibility for handling the fetched resource response belongs to the completion block passed into fetchResource:completion:
. Below
you can find the explanation of the two possible outcomes for fetching resources.
Resource call completion
[client fetchResource:request completion:^(ONGResourceResponse * _Nullable response, NSError * _Nullable error) {
// handle the response
}];
The completion block will be called whenever a fetch resource call is completed. The following values are provided:
response
- the object containing the status code, headers and the bare data containing the body which needs to be decoded.error
- defines the type of error that occurred. Depending on the error reason the following domains are possible:ONGFetchResourceErrorDomain
(only for authenticated resource requests),ONGFetchAnonymousResourceErrorDomain
(only for anonymous requests),ONGFetchUnauthenticatedResourceDomain
(only for unauthenticated resource requests), theONGGenericErrorDomain
in case of a generic error or theNSURLError
in case of a http related error.
Example resource call implementation with a JSON encoded payload
Objective-C
[client fetchResource:request completion:^(ONGResourceResponse * _Nullable response, NSError * _Nullable error) {
if (response && response.statusCode < 400 && response.data) {
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:body options:0 error:nil];
// further mapping of JSON
} else {
// handle error
}
}];
Swift
client.fetchResource(request) { response, error in
if response?.statusCode < 400, let data = response?.data {
do {
let json = try NSJSONSerialization.JSONObjectWithData(data, options: [])
// further response handling
} catch {
// response is not JSON encoded
}
} else {
// handle error
}
}
Handling resource call errors
In case of a resource call failure the SDK will provide an error. Depending on the error reason and resource call type the following domains are possible:
ONGFetchResourceErrorDomain
(only for authenticated requests), ONGFetchAnonymousResourceErrorDomain
(only for anonymous requests), ONGGenericErrorDomain
,
NSUrlError
(in case of http related errors).
Example error handling
Objective-C
[userClient fetchResource:request completion:^(ONGResourceResponse * _Nullable response, NSError * _Nullable error) {
if (error) {
switch(error.code) {
case ONGFetchResourceErrorUserNotAuthenticated:
// user isn't authenticated
break;
case NSURLErrorCancelled:
// cancelled explicitly, ignore
break;
default:
// default error handling
break;
} else {
// regular response handling
}
}
}];
Swift
userClient.fetchResource(request) { response, error in
if let error = error {
switch error.code {
case ONGFetchResourceError.UserNotAuthenticated:
// user isn't authenticated
case NSURLError.Cancelled:
// cancelled explicitly, ignore
break
default:
// default error handling
}
} else {
// regular response handling
}
}
Running resource call handling
Both authenticated and anonymous resource calls return an instance of the ONGNetworkTask
. This object allows you to control and observe the execution by
inspecting various properties:
state
- enumONGNetworkTaskState
, describing whether task is running, suspended, cancelled or completed.identifier
- unique task identifier.request
- request with which the resource call has been made.response
- instance ofONGResourceResponse
. This value fulfilled upon request completion and contains useful information likeHTTP Status Code
, response headers and the actual body of the response. For advanced usage it provides a reference to theNSHTTPURLResponse
object.error
- instance ofNSError
fulfilled in case of a request failure. It might be of theNSURLErrorDomain
orONGGenericErrorDomain
.
You can control tasks through the following methods:
cancel
- cancel a running or suspended task.suspend
- suspend a running task.resume
- resume a suspended task.