| ... | ... | @@ -4,7 +4,6 @@ const std = @import("std"); |
| 4 | 4 | const string = []const u8; |
| 5 | 5 | const files = @import("./files.zig"); |
| 6 | 6 | const pek = @import("pek"); |
| 7 | | const zfetch = @import("zfetch"); |
| 8 | 7 | const extras = @import("extras"); |
| 9 | 8 | const url = @import("url"); |
| 10 | 9 | const http = @import("http"); |
| ... | ... | @@ -299,6 +298,10 @@ pub fn Handlers(comptime T: type) type { |
| 299 | 298 | const client = clientByProviderId(Self.clients, state) orelse return try fail(response_status, body_writer, "error: No handler found for provider: {s}\n", .{state}); |
| 300 | 299 | const code = query.get("code") orelse return try fail(response_status, body_writer, "", .{}); |
| 301 | 300 | |
| 301 | var buf: [4096]u8 = @splat(0); |
| 302 | var http_client: std.http.Client = .{ .allocator = alloc }; |
| 303 | defer http_client.deinit(); |
| 304 | |
| 302 | 305 | var params = url.SearchParams.init(alloc); |
| 303 | 306 | try params.append("client_id", client.id); |
| 304 | 307 | try params.append("client_secret", client.secret); |
| ... | ... | @@ -306,19 +309,28 @@ pub fn Handlers(comptime T: type) type { |
| 306 | 309 | try params.append("code", code); |
| 307 | 310 | try params.append("redirect_uri", try redirectUri(request_headers, alloc, T.callbackPath)); |
| 308 | 311 | try params.append("state", "none"); |
| 312 | const req_body = try params.encode(); |
| 309 | 313 | |
| 310 | | const req = try zfetch.Request.init(alloc, client.provider.token_url, null); |
| 311 | | |
| 312 | | var headers = zfetch.Headers.init(alloc); |
| 313 | | try headers.appendValue("Content-Type", "application/x-www-form-urlencoded"); |
| 314 | | try headers.appendValue("Authorization", try std.fmt.allocPrint(alloc, "Basic {s}", .{try extras.base64EncodeAlloc(alloc, try std.mem.join(alloc, ":", &.{ client.id, client.secret }))})); |
| 315 | | try headers.appendValue("Accept", "application/json"); |
| 316 | | |
| 317 | | try req.do(.POST, headers, try params.encode()); |
| 318 | | const r = req.reader(); |
| 319 | | const body_content = try r.readAllAlloc(alloc, 1024 * 1024 * 5); |
| 320 | | if (req.status != .ok) std.log.scoped(.oauth).debug("{s}: {s}", .{ @tagName(req.status), body_content }); |
| 321 | | if (req.status != .ok) return error.OauthBadToken; |
| 314 | var req = try http_client.open(.POST, try std.Uri.parse(client.provider.token_url), .{ |
| 315 | .server_header_buffer = &buf, |
| 316 | .headers = .{ |
| 317 | .authorization = .{ .override = try std.fmt.allocPrint(alloc, "Basic {s}", .{try extras.base64EncodeAlloc(alloc, try std.mem.join(alloc, ":", &.{ client.id, client.secret }))}) }, |
| 318 | .content_type = .{ .override = "application/x-www-form-urlencoded" }, |
| 319 | }, |
| 320 | .extra_headers = &.{ |
| 321 | .{ .name = "Accept", .value = "application/json" }, |
| 322 | }, |
| 323 | .redirect_behavior = .not_allowed, |
| 324 | }); |
| 325 | defer req.deinit(); |
| 326 | req.transfer_encoding = .{ .content_length = req_body.len }; |
| 327 | try req.send(); |
| 328 | try req.writer().writeAll(req_body); |
| 329 | try req.finish(); |
| 330 | try req.wait(); |
| 331 | const body_content = try req.reader().readAllAlloc(alloc, 1024 * 1024 * 5); |
| 332 | if (req.response.status != .ok) std.log.scoped(.oauth).debug("{s}: {s}", .{ @tagName(req.response.status), body_content }); |
| 333 | if (req.response.status != .ok) return error.OauthBadToken; |
| 322 | 334 | const val = try extras.parse_json(alloc, body_content); |
| 323 | 335 | |
| 324 | 336 | const tt = val.value.object.get("token_type").?.string; |
| ... | ... | @@ -326,16 +338,23 @@ pub fn Handlers(comptime T: type) type { |
| 326 | 338 | |
| 327 | 339 | const at = val.value.object.get("access_token") orelse return try fail(response_status, body_writer, "Identity Provider Login Error!\n{s}", .{body_content}); |
| 328 | 340 | |
| 329 | | const req2 = try zfetch.Request.init(alloc, client.provider.me_url, null); |
| 330 | | var headers2 = zfetch.Headers.init(alloc); |
| 331 | | try headers2.appendValue("Authorization", try std.fmt.allocPrint(alloc, "Bearer {s}", .{at.string})); |
| 332 | | try headers2.appendValue("Accept", "application/json"); |
| 333 | | |
| 334 | | try req2.do(.GET, headers2, null); |
| 335 | | const r2 = req2.reader(); |
| 336 | | const body_content2 = try r2.readAllAlloc(alloc, 1024 * 1024 * 5); |
| 337 | | if (req2.status != .ok) std.log.scoped(.oauth).debug("{s}: {s}", .{ @tagName(req2.status), body_content2 }); |
| 338 | | if (req2.status != .ok) return error.OauthBadUserinfo; |
| 341 | var req2 = try http_client.open(.GET, try std.Uri.parse(client.provider.me_url), .{ |
| 342 | .server_header_buffer = &buf, |
| 343 | .headers = .{ |
| 344 | .authorization = .{ .override = try std.fmt.allocPrint(alloc, "Bearer {s}", .{at.string}) }, |
| 345 | }, |
| 346 | .extra_headers = &.{ |
| 347 | .{ .name = "Accept", .value = "application/json" }, |
| 348 | }, |
| 349 | .redirect_behavior = .not_allowed, |
| 350 | }); |
| 351 | defer req2.deinit(); |
| 352 | try req2.send(); |
| 353 | try req2.finish(); |
| 354 | try req2.wait(); |
| 355 | const body_content2 = try req2.reader().readAllAlloc(alloc, 1024 * 1024 * 5); |
| 356 | if (req2.response.status != .ok) std.log.scoped(.oauth).debug("{s}: {s}", .{ @tagName(req2.response.status), body_content2 }); |
| 357 | if (req2.response.status != .ok) return error.OauthBadUserinfo; |
| 339 | 358 | const val2 = try extras.parse_json(alloc, body_content2); |
| 340 | 359 | |
| 341 | 360 | const id = try fixId(alloc, val2.value.object.get(client.provider.id_prop).?); |