/// <summary> /// Determines if the user is authorized to access the WebAPI endpoint based on the bearer token /// </summary> protected override bool IsAuthorized(HttpActionContext actionContext) { try { // Parse the query string and ensure there is an access_token var queryParams = parseRequestParams(actionContext.Request.RequestUri.Query); if (!queryParams.ContainsKey("access_token")) return false; // Get the details of the WOPI request WopiRequest requestData = new WopiRequest() { RequestType = WopiRequestType.None, AccessToken = queryParams["access_token"], Id = actionContext.RequestContext.RouteData.Values["id"].ToString() }; // Get the requested file from Document DB var itemId = new Guid(requestData.Id); var file = DocumentDBRepository<DetailedFileModel>.GetItem("Files", i => i.id == itemId); // Check for missing file if (file == null) return false; // Validate the access token return WopiSecurity.ValidateToken(requestData.AccessToken, file.Container, file.id.ToString()); } catch (Exception) { // Any exception will return false, but should probably return an alternate status codes return false; } }
/// <summary> /// Called at the beginning of a WOPI request to parse the request and determine the request type /// </summary> public static WopiRequest ParseRequest(HttpRequest request) { // Initilize wopi request data object with default values WopiRequest requestData = new WopiRequest() { RequestType = WopiRequestType.None, AccessToken = request.QueryString["access_token"], Id = "" }; // Get request path, e.g. /<...>/wopi/files/<id> string requestPath = request.Url.AbsolutePath.ToLower(); // Remove /<...>/wopi/ string wopiPath = requestPath.Substring(requestPath.IndexOf(WopiUtil.WOPI_BASE_PATH) + WopiUtil.WOPI_BASE_PATH.Length); // Check the type of request being made if (wopiPath.StartsWith(WopiUtil.WOPI_FILES_PATH)) { // This is a file-related request // Remove /files/ from the beginning of wopiPath string rawId = wopiPath.Substring(WopiUtil.WOPI_FILES_PATH.Length); if (rawId.EndsWith(WopiUtil.WOPI_CONTENTS_PATH)) { // The rawId ends with /contents so this is a request to read/write the file contents // Remove /contents from the end of rawId to get the actual file id requestData.Id = rawId.Substring(0, rawId.Length - WopiUtil.WOPI_CONTENTS_PATH.Length); // Check request verb to determine file operation if (request.HttpMethod == "GET") requestData.RequestType = WopiRequestType.GetFile; if (request.HttpMethod == "POST") requestData.RequestType = WopiRequestType.PutFile; } else { requestData.Id = rawId; if (request.HttpMethod == "GET") { // GET requests to the file are always CheckFileInfo requestData.RequestType = WopiRequestType.CheckFileInfo; } else if (request.HttpMethod == "POST") { // Use the X-WOPI-Override header to determine the request type for POSTs string wopiOverride = request.Headers[WopiRequestHeaders.OVERRIDE]; switch (wopiOverride) { case "LOCK": // Check lock type based on presence of OldLock header if (request.Headers[WopiRequestHeaders.OLD_LOCK] != null) requestData.RequestType = WopiRequestType.UnlockAndRelock; else requestData.RequestType = WopiRequestType.Lock; break; case "GET_LOCK": requestData.RequestType = WopiRequestType.GetLock; break; case "REFRESH_LOCK": requestData.RequestType = WopiRequestType.RefreshLock; break; case "UNLOCK": requestData.RequestType = WopiRequestType.Unlock; break; case "PUT_RELATIVE": requestData.RequestType = WopiRequestType.PutRelativeFile; break; case "RENAME_FILE": requestData.RequestType = WopiRequestType.RenameFile; break; case "PUT_USER_INFO": requestData.RequestType = WopiRequestType.PutUserInfo; break; /* // The following WOPI_Override values were referenced in the product group sample, but not in the documentation case "COBALT": requestData.RequestType = WopiRequestType.ExecuteCobaltRequest; break; case "DELETE": requestData.RequestType = WopiRequestType.DeleteFile; break; case "READ_SECURE_STORE": requestData.RequestType = WopiRequestType.ReadSecureStore; break; case "GET_RESTRICTED_LINK": requestData.RequestType = WopiRequestType.GetRestrictedLink; break; case "REVOKE_RESTRICTED_LINK": requestData.RequestType = WopiRequestType.RevokeRestrictedLink; break; */ } } } } else if (wopiPath.StartsWith(WopiUtil.WOPI_FOLDERS_PATH)) { // This is a folder-related request // Remove /folders/ from the beginning of wopiPath string rawId = wopiPath.Substring(WopiUtil.WOPI_FOLDERS_PATH.Length); if (rawId.EndsWith(WopiUtil.WOPI_CHILDREN_PATH)) { // rawId ends with /children, so it's an EnumerateChildren request. // Remove /children from the end of rawId requestData.Id = rawId.Substring(0, WopiUtil.WOPI_CHILDREN_PATH.Length); //requestData.RequestType = WopiRequestType.EnumerateChildren; } else { // rawId doesn't end with /children, so it's a CheckFolderInfo. requestData.Id = rawId; //requestData.RequestType = WopiRequestType.CheckFolderInfo; } } else { // This is an unknown request requestData.RequestType = WopiRequestType.None; } return requestData; }