Created
June 1, 2018 01:24
-
-
Save Andrew-Lees11/80253ffab4cedc83fbf1f78bb6d91dc2 to your computer and use it in GitHub Desktop.
TypeSafeCreds Redirect unauthorized
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Copyright IBM Corporation 2018 | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
**/ | |
import Kitura | |
import KituraNet | |
import KituraContracts | |
import LoggerAPI | |
import Foundation | |
public protocol TypeSafeCredentials: TypeSafeMiddleware { | |
/// The unique identifier for the authentication providers | |
var id: String { get } | |
/// The name of the authentication provider | |
var provider: String { get } | |
static var redirectUnauthorized: String? { get } | |
/// Authenticate an incoming request. | |
/// | |
/// - Parameter request: The `RouterRequest` object used to get information | |
/// about the request. | |
/// - Parameter response: The `RouterResponse` object used to respond to the | |
/// request. | |
/// - Parameter options: The dictionary of plugin specific options. | |
/// - Parameter onSuccess: The closure to invoke in the case of successful authentication. | |
/// - Parameter onFailure: The closure to invoke in the case of an authentication failure. | |
/// - Parameter onPass: The closure to invoke when the plugin doesn't recognize the | |
/// authentication data (usually an authentication token) in the request. | |
/// - Parameter inProgress: The closure to invoke to cause a redirect to the login page in the | |
/// case of redirecting authentication. | |
static func authenticate (request: RouterRequest, response: RouterResponse, | |
onSuccess: @escaping (Self) -> Void, | |
onFailure: @escaping (HTTPStatusCode?, [String:String]?) -> Void, | |
onPass: @escaping (HTTPStatusCode?, [String:String]?) -> Void | |
) | |
} | |
extension TypeSafeCredentials { | |
public var redirectUnauthorized: String? { | |
return nil | |
} | |
/// Handle an incoming request: authenticate the request using the registered plugin. | |
/// | |
/// - Parameter request: The `RouterRequest` object used to get information | |
/// about the request. | |
/// - Parameter response: The `RouterResponse` object used to respond to the | |
/// request. | |
/// - Parameter next: The closure to invoke to enable the Router to check for | |
/// other handlers or middleware to work with this request. | |
public static func handle(request: RouterRequest, response: RouterResponse, completion: @escaping (Self?, RequestError?) -> Void) { | |
authenticate(request: request, response: response, | |
onSuccess: { selfInstance in | |
completion(selfInstance, nil) | |
}, | |
onFailure: { status, headers in | |
redirectUnauthorized(response: response) | |
fail(response: response, status: status, headers: headers) | |
}, | |
onPass: { status, headers in | |
if let headers = headers { | |
for (key, value) in headers { | |
response.headers.append(key, value: value) | |
} | |
} | |
redirectUnauthorized(response: response) | |
completion(nil, RequestError(httpCode: status?.rawValue ?? 401)) | |
} | |
) | |
} | |
private static func fail (response: RouterResponse, status: HTTPStatusCode?, headers: [String:String]?) { | |
let responseStatus = status ?? .unauthorized | |
if let headers = headers { | |
for (key, value) in headers { | |
response.headers.append(key, value: value) | |
} | |
} | |
do { | |
try response.status(responseStatus).end() | |
} | |
catch { | |
Log.error("Failed to send response") | |
} | |
} | |
private static func redirectUnauthorized (response: RouterResponse) { | |
if let redirect = Self.redirectUnauthorized { | |
do { | |
try response.redirect(redirect) | |
} | |
catch { | |
response.error = NSError(domain: "Credentials", code: 1, userInfo: [NSLocalizedDescriptionKey: "Failed to redirect unauthorized request"]) | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment