View
206
Download
2
Tags:
Embed Size (px)
DESCRIPTION
There is a computer in your pocket, and mine. Though lets be honest, beyond email, Organizations though are still struggling to make use of these smart devices that they are already paying for. The reason is simple, Imagine a computer, with an inferior processor, poor connectivity, smaller screen, and easily lost and used for personal purposes. Add to it, multiple platforms, and an incredibly fast release cadence. In this fast paced session, Sahil will demonstrate mobile apps targeting the SharePoint and Office 365 platforms demonstrating what you, the Microsoft developer needs to learn and be on top of going forward. And yes, you need to broaden your horizons past C# too. But don’t worry, even if you have never worked with iOS before, there is plenty to chew on in this session.
Citation preview
Training and Consulting: [email protected]
Mobile devices and [email protected]/SAHILMALIKLINKED.IN/SAHIL
Sahil Malik
Training and Consulting: [email protected]
Training and Consulting: [email protected]
Before I waste your time ..
1. This talk is important. We will all be writing mobile apps in the future.2. The first 10-15 minutes are generic – even if you are not a developer you will benefit from it.3. Rest of the talk is 100% dev centric.4. Concepts involved,
1. SharePoint Apps/Office3652. ASP.NET MVC 53. Owin/Oauth4. JavaScript and AngularJS5. Swift/ObjectiveC
5. It is okay to not be an expert at all of these.
Training and Consulting: [email protected]
Mobile Devices and SharePoint
Mobile Devices and Office 365
Mobile Devices and Microsoft developers
Mobile Devices and .. Why just Microsoft?
Training and Consulting: [email protected]
The conventional Microsoft developer is dead
Training and Consulting: [email protected]
Challenges to solve• Platform• HTML5• Hybrid• Xamarin Native• Platform Native
• Connectivity• Enterprise data is on premises• Mobile devices and Active Directory don’t mix easily (yet!)
• Security• Enterprise apps• Open App store apps
Training and Consulting: [email protected]
Security• OAuth is the way to go• Claims is the only choice• Token management is something you need to understand
• Never use embedded web views for authentication• Common mistakes• IT Administrators are trying to solve Mobile devices with the
same approach they used for windows active directory• VPN
• Per App VPN is finally usable in limited scenarios with many downsides. Yet for enterprise scenarios this is the choice
• End to End encryption• Device Management for enterprise scenarios
Training and Consulting: [email protected]
Connectivity• Easy: Device to cloud• iOS app talking to Office 365
• Direct http connectivity (well with a middle layer, I’ll explain in a moment why!)
• Tough: Device to on premises• iOS app talking to on-prem SharePoint
• Azure Service Bus, NServiceBus, JBOSS FUSE etc.• BiDirectional TCP channels• Azure remote endpoints• Per App VPN connections
• Important Best Practice: Design your app logic independent of the communications layer
Training and Consulting: [email protected]
Platform• HTML 5• Maximum reach• Difficult to get UI 100% right, but UI can scale. Even iOS has
multiple device sizes now.• No need to go through App Stores• Native Device capabilities are poorer• Offline experience is very hard to get right.
Training and Consulting: [email protected]
Platform• Hybrid
• The best choice in my opinion if you are targeting multiple platforms
• You do need to go through app stores• You cannot update anything you wish at your whim (app stores
may block you)• Needs lots of experience to get this right and be 100% native
and responsive
• iOS8 no longer throttles hosted safari• What is possible with this?
• phonegap.com/app/ios/
• It still needs you to learn Swift/ObjectiveC/Java etc. Windows UI is the toughest to get right.
Training and Consulting: [email protected]
Platform• Xamarin• Promotes reuse of logic written in C#
• Not every .NET class is reusable.• And, how much reusable logic do you have IN the app? Usually its REST
services.• Common scenarios such as offline scenarios are already solved.• The project structure, builds, release management becomes
complicated.• ObjectiveC sucks, but Swift is not so bad!
• It’s a technical marvel. But how much value does it really have!?• But, as a consultant, I need to learn Xamarin.
Training and Consulting: [email protected]
Platform• Native• Best of everything, except you need to write your app for each
platform.• Swift and ObjectiveC can co-exist.• Swift is like C# with an Apple personality (because of it’s
retarded ObjectiveC brother). Still its pretty good.
Training and Consulting: [email protected]
C:\>whoami
12xMVP 15xAuthor Pluralsight AuthorFunny and Honest
HTTP://BLAH.WINSMARTS.COM@SAHILMALIK
Training and Consulting: [email protected]
So lets talk some Architecture
Training and Consulting: [email protected]
Your App SDK Office 365
• App hard tied to Office 365• Secrets embedded in apps will expire, you cannot control when you update the app, because you don’t update it• Your mobile app, is also an Office 365 App. You are limited by the security model they offer• You may want to reuse your Mobile app investments for back-ends other than Office 365.• Your authentication is tied to Azure AD. Your customer may not be.• SDKs for iOS may not get the same love as .NET classes will
Training and Consulting: [email protected]
Your AppStandards
based communicati
on
Office 365
• Standards! Yeah!• You can update the ASP.NET backend, without users having to update the app• You can offer security that makes sense for you, and map it to diverse back ends.• You can add/remove support back ends at your whim.• Authentication can be whatever you wish, even though backend can be Azure AD.
ASP.NET WebAPI
My preferred approach
Training and Consulting: [email protected]
Mobile backend• An ASP.NET MVC WebAPI site that supports OAuth and
CORS.
Training and Consulting: [email protected]
Step 1: Create ASP.NET MVC ProjectBasic Setup
Training and Consulting: [email protected]
Step 2: Add Nuget PackagesInstall-Package Microsoft.AspNet.WebApi.Owin –Version 5.1.2Install-Package Microsoft.Owin.Host.SystemWeb –Version 2.1.0
Basic Setup
Training and Consulting: [email protected]
Step 3: Add OWIN Startup.csusing Microsoft.Owin;using Owin;using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Http; [assembly: OwinStartup(typeof(AngularJSAuthentication.API.Startup))]namespace AngularJSAuthentication.API{ public class Startup { public void Configuration(IAppBuilder app) { HttpConfiguration config = new HttpConfiguration(); WebApiConfig.Register(config); app.UseWebApi(config); } }}
// also delete global.asax – you don’t need it, this will suffice
Basic Setup
Training and Consulting: [email protected]
Step 4: App_Start\WebApiConfig.csusing System;using System.Collections.Generic;using System.Linq;using System.Net.Http.Formatting;using System.Web.Http;using Newtonsoft.Json.Serialization; namespace MobileBackEnd{ public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First(); jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); } }}
Basic Setup
Training and Consulting: [email protected]
Step 5: Setup AuthenticationInstall-Package Microsoft.AspNet.Identity.Owin -Version 2.0.1Install-Package Microsoft.AspNet.Identity.EntityFramework -Version 2.0.1
using System;using System.Collections.Generic;using System.Linq;using System.Web;using Microsoft.AspNet.Identity.EntityFramework; namespace MobileBackEnd{ public class AuthContext : IdentityDbContext<IdentityUser> { public AuthContext() : base("AuthContext") { } }}
Add a class called AuthContext.cs
<connectionStrings><add name="AuthContext" connectionString="Data Source=SP; Initial Catalog=Users;User Id=sa;Password=p@ssword1" providerName="System.Data.SqlClient"/></connectionStrings>
And add the supporting connection string
Authentication
Training and Consulting: [email protected]
Step 6: Authentication .. Models\UserModel.cs
using System;using System.Collections.Generic;using System.ComponentModel.DataAnnotations;using System.Linq;using System.Web; namespace MobileBackEnd.Models{ public class UserModel { [Required] [Display(Name = "User name")] public string UserName { get; set; } [Required] [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] [DataType(DataType.Password)] [Display(Name = "Password")] public string Password { get; set; } }}
Authentication
Training and Consulting: [email protected]
Step 7: Add AuthRepositoryusing System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;using System.Web;using Microsoft.AspNet.Identity;using Microsoft.AspNet.Identity.EntityFramework;using MobileBackEnd.Models;
namespace MobileBackEnd{ public class AuthRepository : IDisposable { private AuthContext ctx; private UserManager<IdentityUser> userMgr; public AuthRepository() { ctx = new AuthContext(); userMgr = new UserManager<IdentityUser>(new UserStore<IdentityUser>(ctx)); } public async Task<IdentityResult> RegisterUser(UserModel userModel) { IdentityUser user = new IdentityUser { UserName = userModel.UserName}; var result = await userMgr.CreateAsync(user, userModel.Password); return result; } public async Task<IdentityUser> FindUser(string userName, string password) { IdentityUser user = await userMgr.FindAsync(userName, password); return user; } public void Dispose() { ctx.Dispose(); userMgr.Dispose(); } }}
Authentication
Training and Consulting: [email protected]
Step 8: Add an AccountController.csusing System;using System.Collections.Generic;using System.Linq;using System.Net;using System.Net.Http;using System.Threading.Tasks;using System.Web.Http;using Microsoft.AspNet.Identity;using MobileBackEnd.Models;
namespace MobileBackEnd.Controllers{ [RoutePrefix("api/Account")] public class AccountController : ApiController { private AuthRepository repo = null; public AccountController() { repo = new AuthRepository();} [AllowAnonymous] [Route("Register")] public async Task<IHttpActionResult> Register(UserModel userModel) { if (!ModelState.IsValid) return BadRequest(ModelState); IdentityResult result = await repo.RegisterUser(userModel); IHttpActionResult errorResult = GetErrorResult(result); if (errorResult != null) return errorResult; return Ok(); } protected override void Dispose(bool disposing) { if (disposing) repo.Dispose(); base.Dispose(disposing); } private IHttpActionResult GetErrorResult(IdentityResult result) { if (result == null) return InternalServerError(); if (!result.Succeeded) { if (result.Errors != null) { foreach (string error in result.Errors) { ModelState.AddModelError("", error); } } if (ModelState.IsValid) return BadRequest(); return BadRequest(ModelState); } return null; } }}
Authentication
Training and Consulting: [email protected]
Step 9: Create a user
{“username”:”Sahil”, “password”:”p@ssword1”}
Authentication
Training and Consulting: [email protected]
Step 10: Add SPWebController.csusing System;using System.Collections.Generic;using System.Linq;using System.Net;using System.Net.Http;using System.Web.Http; namespace MobileBackEnd.Controllers{ [RoutePrefix("api/SPWeb")] public class SPWebController : ApiController { [Authorize] [Route("title")] public IHttpActionResult Get() { return Ok("Dummy title for now"); } }}
Business Logic
If you visit /api/SPWeb/title.. You will get a 401 unauthorized
Training and Consulting: [email protected]
Step 11: Add support for OAuthAuthentication
Install-Package Microsoft.Owin.Security.Oauth –Version 2.1.0
using System;using System.Collections.Generic;using System.Linq;using System.Security.Claims;using System.Threading.Tasks;using System.Web;using Microsoft.AspNet.Identity.EntityFramework;using Microsoft.Owin.Security.OAuth;
Add a UserNamePasswordAuthorizationProvider.cs
Training and Consulting: [email protected]
Step 11: UserNamePasswordAuthorizationProvider.csnamespace MobileBackEnd{ public class UsernamePasswordAuthorizationProvider : OAuthAuthorizationServerProvider { public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) { context.Validated(); } public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) { context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" }); using (AuthRepository repo = new AuthRepository()) { IdentityUser user = await repo.FindUser(context.UserName, context.Password); if (user == null) { context.SetError("invalid_grant", "Incorrect username password."); return; } } var identity = new ClaimsIdentity(context.Options.AuthenticationType); identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName)); context.Validated(identity); } }}
Authentication
Training and Consulting: [email protected]
Step 12: Hook in the UPAuthProvider• In the Startup.cs file, in the Configuration Method,
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions(){ AllowInsecureHttp = true, TokenEndpointPath = new PathString("/token"), AccessTokenExpireTimeSpan = TimeSpan.FromDays(1), Provider = new UsernamePasswordAuthorizationProvider()}; app.UseOAuthAuthorizationServer(OAuthServerOptions);app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
Authentication
Training and Consulting: [email protected]
Step 13: Add support for CORSInstall-Package Microsoft.Owin.Cors –Version 2.1.0
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
And add the below in Startup.cs
CORS
Training and Consulting: [email protected]
Lets test it out!Authentication
Training and Consulting: [email protected]
Lets test it out ..Authentication
Training and Consulting: [email protected]
Step 14: Add business logic• Turn it into a SharePoint app
Training and Consulting: [email protected]
Step 15: Modify SPWebControllerpublic IHttpActionResult Get(){ Uri siteUri = new Uri("https://winsmartsdev.sharepoint.com"); string realm = TokenHelper.GetRealmFromTargetUrl(siteUri); string accessToken = TokenHelper.GetAppOnlyAccessToken( TokenHelper.SharePointPrincipal, siteUri.Authority, realm).AccessToken; using (var clientContext = TokenHelper.GetClientContextWithAccessToken(“https://winsmartsdev.sharepoint.com", accessToken)) { if (clientContext != null) { clientContext.Load(clientContext.Web); clientContext.ExecuteQuery(); return Ok(clientContext.Web.Title); } else return Ok("Title not found"); } }}
yes you will also have to use AppRegNew.aspx etc. to install the app ..
Training and Consulting: [email protected]
Retest
Training and Consulting: [email protected]
GREAT! NOW LETS WRITE THE APP!
Training and Consulting: [email protected]
The App• Native or Hybrid• Both are possible, but I’ll show Hybrid
• AngularJS SPA with 2 pages• SignIn• Home
Training and Consulting: [email protected]
Step #1: The basics of the app• Views• Controllers• And routing between them
Training and Consulting: [email protected]
Step #1c: The screens - controllersloginController.js
Homecontroller.js
Training and Consulting: [email protected]
Step #2: Authentication
Training and Consulting: [email protected]
Step #2b: Auth interceptor
Training and Consulting: [email protected]
Step #3: Debugging• Chrome dev tools
Training and Consulting: [email protected]
Step #3b: Debugging – iOS Simulator• Xcode and Visual Studio
Training and Consulting: [email protected]
questions?
HTTP://WWW.WINSMARTS.COM/CONTACT.ASPX
@SAHILMALIK
Training and Consulting: [email protected]
thank you.
SHAREPOINT AND PROJECT CONFERENCE ADRIATICS ZAGREB, 10/15/2014 - 10/16/2014